openapi: 3.0.3
info:
  title: 'Go Links API Documentation'
  description: 'GoLinks API - Manage your Go Links, tags, and permissions programmatically.'
  version: 1.0.0
servers:
  -
    url: 'http://localhost'
tags:
  -
    name: Links
    description: "\nAPIs for managing Go Links"
  -
    name: Tags
    description: "\nAPIs for managing tags"
components:
  securitySchemes:
    default:
      type: http
      scheme: bearer
      description: 'You can retrieve your API token by click the user profile dropdown in the upper right-hand corner, selecting <strong>API Access</strong>, and generating a new personal access token.'
security:
  -
    default: []
paths:
  /api/v2/links:
    get:
      summary: 'Get Links'
      operationId: getLinks
      description: "Retrieve all links accessible to the authenticated user.\nThis includes links owned by the user and links shared with them."
      parameters:
        -
          in: query
          name: page
          description: 'Page number for pagination.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'Page number for pagination.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of results per page (max 100).'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of results per page (max 100).'
            example: 15
        -
          in: query
          name: 'filter[owned]'
          description: 'Filter to only show owned links.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Filter to only show owned links.'
            example: true
        -
          in: query
          name: 'filter[shared]'
          description: 'Filter to only show shared links.'
          example: false
          required: false
          schema:
            type: boolean
            description: 'Filter to only show shared links.'
            example: false
        -
          in: query
          name: 'filter[enabled]'
          description: 'Filter by enabled status.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Filter by enabled status.'
            example: true
        -
          in: query
          name: 'filter[tag]'
          description: 'Filter by tag label.'
          example: important
          required: false
          schema:
            type: string
            description: 'Filter by tag label.'
            example: important
        -
          in: query
          name: 'filter[search]'
          description: 'Search in link strings and target URLs.'
          example: example
          required: false
          schema:
            type: string
            description: 'Search in link strings and target URLs.'
            example: example
        -
          in: query
          name: sort
          description: 'Sort field (string, target_url, created_at, hit_count). Default: created_at.'
          example: hit_count
          required: false
          schema:
            type: string
            description: 'Sort field (string, target_url, created_at, hit_count). Default: created_at.'
            example: hit_count
        -
          in: query
          name: order
          description: 'Sort order (asc, desc). Default: desc.'
          example: desc
          required: false
          schema:
            type: string
            description: 'Sort order (asc, desc). Default: desc.'
            example: desc
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: 1
                      string: example
                      target_url: 'https://example.com'
                      enabled: true
                      hit_count: 42
                      http_status_code: 200
                      last_status_check_at: '2025-11-21 10:30:00'
                      exclude_from_status_check: false
                      created_at: '2025-11-01T12:00:00.000000Z'
                      updated_at: '2025-11-21T10:30:00.000000Z'
                      owner:
                        id: 1
                        name: 'John Doe'
                        unity_id: jdoe
                      tags:
                        -
                          id: 1
                          label: important
                          name: important
                      is_owner: true
                      is_shared: false
                  meta:
                    current_page: 1
                    per_page: 15
                    total: 42
                    last_page: 3
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: 1
                        string: example
                        target_url: 'https://example.com'
                        enabled: true
                        hit_count: 42
                        http_status_code: 200
                        last_status_check_at: '2025-11-21 10:30:00'
                        exclude_from_status_check: false
                        created_at: '2025-11-01T12:00:00.000000Z'
                        updated_at: '2025-11-21T10:30:00.000000Z'
                        owner:
                          id: 1
                          name: 'John Doe'
                          unity_id: jdoe
                        tags:
                          -
                            id: 1
                            label: important
                            name: important
                        is_owner: true
                        is_shared: false
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        string:
                          type: string
                          example: example
                        target_url:
                          type: string
                          example: 'https://example.com'
                        enabled:
                          type: boolean
                          example: true
                        hit_count:
                          type: integer
                          example: 42
                        http_status_code:
                          type: integer
                          example: 200
                        last_status_check_at:
                          type: string
                          example: '2025-11-21 10:30:00'
                        exclude_from_status_check:
                          type: boolean
                          example: false
                        created_at:
                          type: string
                          example: '2025-11-01T12:00:00.000000Z'
                        updated_at:
                          type: string
                          example: '2025-11-21T10:30:00.000000Z'
                        owner:
                          type: object
                          properties:
                            id:
                              type: integer
                              example: 1
                            name:
                              type: string
                              example: 'John Doe'
                            unity_id:
                              type: string
                              example: jdoe
                        tags:
                          type: array
                          example:
                            -
                              id: 1
                              label: important
                              name: important
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                                example: 1
                              label:
                                type: string
                                example: important
                              name:
                                type: string
                                example: important
                        is_owner:
                          type: boolean
                          example: true
                        is_shared:
                          type: boolean
                          example: false
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 15
                      total:
                        type: integer
                        example: 42
                      last_page:
                        type: integer
                        example: 3
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
      tags:
        - Links
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                  description: 'Must be at least 1. Must not be greater than 100.'
                  example: 1
                filter:
                  type: object
                  description: ''
                  example: []
                  properties:
                    owned:
                      type: boolean
                      description: ''
                      example: true
                    shared:
                      type: boolean
                      description: ''
                      example: false
                    enabled:
                      type: boolean
                      description: ''
                      example: false
                    tag:
                      type: string
                      description: ''
                      example: architecto
                    search:
                      type: string
                      description: ''
                      example: architecto
                sort:
                  type: string
                  description: ''
                  example: null
                order:
                  type: string
                  description: ''
                  example: null
    post:
      summary: 'Create Link'
      operationId: createLink
      description: "Create a new Go Link. If no custom string is provided, a random 7-character string will be generated.\nUsers need the appropriate permissions to create random or custom links."
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  string: my-link
                  target_url: 'https://example.com'
                  enabled: true
                  hit_count: 0
                  http_status_code: null
                  last_status_check_at: null
                  exclude_from_status_check: false
                  created_at: '2025-11-21T12:00:00.000000Z'
                  updated_at: '2025-11-21T12:00:00.000000Z'
                  owner:
                    id: 1
                    name: 'John Doe'
                    unity_id: jdoe
                  tags:
                    -
                      id: 1
                      label: important
                      name: important
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique link identifier (read-only).'
                    enum: []
                  string:
                    type: string
                    example: my-link
                    description: 'The short link code (read-only after creation).'
                    enum: []
                  target_url:
                    type: string
                    example: 'https://example.com'
                    description: 'The destination URL (writable).'
                    enum: []
                  enabled:
                    type: boolean
                    example: true
                    description: 'Whether the link is enabled (writable).'
                    enum: []
                  hit_count:
                    type: integer
                    example: 0
                    description: 'Total number of times the link has been accessed (read-only).'
                    enum: []
                  http_status_code:
                    type: string
                    example: null
                    description: 'HTTP status code from last health check (read-only).'
                    enum: []
                  last_status_check_at:
                    type: string
                    example: null
                    description: 'Timestamp of last status check (read-only).'
                    enum: []
                  exclude_from_status_check:
                    type: boolean
                    example: false
                    description: 'Whether to exclude from automated health checks (writable, staff only).'
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-21T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-21T12:00:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
                  owner:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                        description: "Owner's user ID (read-only)."
                        enum: []
                      name:
                        type: string
                        example: 'John Doe'
                        description: "Owner's full name (read-only)."
                        enum: []
                      unity_id:
                        type: string
                        example: jdoe
                        description: "Owner's Unity ID (read-only)."
                        enum: []
                    description: 'The link owner details (read-only).'
                  tags:
                    type: array
                    example:
                      -
                        id: 1
                        label: important
                        name: important
                    description: 'Associated tags (managed via separate endpoints).'
                    enum: []
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        label:
                          type: string
                          example: important
                        name:
                          type: string
                          example: important
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to create custom links.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to create custom links.'
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The given data was invalid.'
                  errors:
                    string:
                      - 'That Go Link (my-link) has already been taken!'
                    target_url:
                      - 'The target url field is required.'
                properties:
                  message:
                    type: string
                    example: 'The given data was invalid.'
                  errors:
                    type: object
                    properties:
                      string:
                        type: array
                        example:
                          - 'That Go Link (my-link) has already been taken!'
                        items:
                          type: string
                      target_url:
                        type: array
                        example:
                          - 'The target url field is required.'
                        items:
                          type: string
      tags:
        - Links
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                string:
                  type: string
                  description: 'Optional custom link string (requires "create custom links" permission). Must be lowercase alphanumeric with hyphens, underscores, or periods.'
                  example: my-link
                  nullable: true
                target_url:
                  type: string
                  description: 'The destination URL (must include http:// or https://).'
                  example: 'https://example.com'
                enabled:
                  type: boolean
                  description: 'Whether the link is enabled. Default: true.'
                  example: true
                exclude_from_status_check:
                  type: boolean
                  description: 'Exclude from automated status checks (staff only). Default: false.'
                  example: false
                tag_id:
                  type: integer
                  description: 'Optional tag ID to attach to the link.'
                  example: 1
                share_with:
                  type: string
                  description: 'Optional Unity ID or Google Group email to share with.'
                  example: jdoe
                  nullable: true
              required:
                - target_url
  /api/v2/links/bulk-update:
    patch:
      summary: 'Bulk Update Links'
      operationId: bulkUpdateLinks
      description: "Update the target URL for multiple links in a single request.\nEach link is independently authorized — you must have manage permissions for each link.\nLinks you cannot manage or that do not exist will be returned in the errors array."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  updated:
                    -
                      string: my-link
                      target_url: 'https://example.com/new'
                  errors:
                    -
                      string: bad-link
                      error: 'Link not found'
                    -
                      string: other-link
                      error: Unauthorized
                properties:
                  updated:
                    type: array
                    example:
                      -
                        string: my-link
                        target_url: 'https://example.com/new'
                    items:
                      type: object
                      properties:
                        string:
                          type: string
                          example: my-link
                        target_url:
                          type: string
                          example: 'https://example.com/new'
                  errors:
                    type: array
                    example:
                      -
                        string: bad-link
                        error: 'Link not found'
                      -
                        string: other-link
                        error: Unauthorized
                    items:
                      type: object
                      properties:
                        string:
                          type: string
                          example: bad-link
                        error:
                          type: string
                          example: 'Link not found'
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The given data was invalid.'
                  errors:
                    links.0.target_url:
                      - 'Please include http:// or https://'
                properties:
                  message:
                    type: string
                    example: 'The given data was invalid.'
                  errors:
                    type: object
                    properties:
                      links.0.target_url:
                        type: array
                        example:
                          - 'Please include http:// or https://'
                        items:
                          type: string
      tags:
        - Links
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                links:
                  type: array
                  description: 'Array of link updates (max 50).'
                  example:
                    -
                      string: my-link
                      target_url: 'https://example.com/new'
                  items:
                    type: string
              required:
                - links
  '/api/v2/links/{string}':
    get:
      summary: 'Get Link'
      operationId: getLink
      description: 'Retrieve a specific link by its string identifier.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  string: my-link
                  target_url: 'https://example.com'
                  enabled: true
                  hit_count: 42
                  http_status_code: 200
                  last_status_check_at: '2025-11-21 10:30:00'
                  exclude_from_status_check: false
                  created_at: '2025-11-01T12:00:00.000000Z'
                  updated_at: '2025-11-21T10:30:00.000000Z'
                  owner:
                    id: 1
                    name: 'John Doe'
                    unity_id: jdoe
                  tags:
                    -
                      id: 1
                      label: important
                      name: important
                  rules:
                    -
                      id: 1
                      value: admins@ncsu.edu
                      created_at: '2025-11-01T12:00:00.000000Z'
                      updated_at: '2025-11-01T12:00:00.000000Z'
                    -
                      id: 2
                      value: jsmith@ncsu.edu
                      created_at: '2025-11-02T14:30:00.000000Z'
                      updated_at: '2025-11-02T14:30:00.000000Z'
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique link identifier (read-only).'
                    enum: []
                  string:
                    type: string
                    example: my-link
                    description: 'The short link code (read-only).'
                    enum: []
                  target_url:
                    type: string
                    example: 'https://example.com'
                    description: 'The destination URL (writable).'
                    enum: []
                  enabled:
                    type: boolean
                    example: true
                    description: 'Whether the link is enabled (writable).'
                    enum: []
                  hit_count:
                    type: integer
                    example: 42
                    description: 'Total number of times the link has been accessed (read-only).'
                    enum: []
                  http_status_code:
                    type: integer
                    example: 200
                    description: 'HTTP status code from last health check (read-only).'
                    enum: []
                  last_status_check_at:
                    type: string
                    example: '2025-11-21 10:30:00'
                    description: 'Timestamp of last status check (read-only).'
                    enum: []
                  exclude_from_status_check:
                    type: boolean
                    example: false
                    description: 'Whether to exclude from automated health checks (writable, staff only).'
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-01T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-21T10:30:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
                  owner:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                        description: "Owner's user ID (read-only)."
                        enum: []
                      name:
                        type: string
                        example: 'John Doe'
                        description: "Owner's full name (read-only)."
                        enum: []
                      unity_id:
                        type: string
                        example: jdoe
                        description: "Owner's Unity ID (read-only)."
                        enum: []
                    description: 'The link owner details (read-only).'
                  tags:
                    type: array
                    example:
                      -
                        id: 1
                        label: important
                        name: important
                    description: 'Associated tags (managed via separate endpoints).'
                    enum: []
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        label:
                          type: string
                          example: important
                        name:
                          type: string
                          example: important
                  rules:
                    type: array
                    example:
                      -
                        id: 1
                        value: admins@ncsu.edu
                        created_at: '2025-11-01T12:00:00.000000Z'
                        updated_at: '2025-11-01T12:00:00.000000Z'
                      -
                        id: 2
                        value: jsmith@ncsu.edu
                        created_at: '2025-11-02T14:30:00.000000Z'
                        updated_at: '2025-11-02T14:30:00.000000Z'
                    description: 'Access control rules (read-only, no API endpoint to modify).'
                    enum: []
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        value:
                          type: string
                          example: admins@ncsu.edu
                        created_at:
                          type: string
                          example: '2025-11-01T12:00:00.000000Z'
                        updated_at:
                          type: string
                          example: '2025-11-01T12:00:00.000000Z'
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to view this link.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to view this link.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
      tags:
        - Links
    patch:
      summary: 'Update Link'
      operationId: updateLink
      description: 'Update an existing link. You must be the owner or have manage permissions.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  string: my-link
                  target_url: 'https://newexample.com'
                  enabled: false
                  hit_count: 42
                  http_status_code: 200
                  last_status_check_at: '2025-11-21 10:30:00'
                  exclude_from_status_check: true
                  created_at: '2025-11-01T12:00:00.000000Z'
                  updated_at: '2025-11-21T12:30:00.000000Z'
                  owner:
                    id: 1
                    name: 'John Doe'
                    unity_id: jdoe
                  tags: []
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique link identifier (read-only).'
                    enum: []
                  string:
                    type: string
                    example: my-link
                    description: 'The short link code (read-only).'
                    enum: []
                  target_url:
                    type: string
                    example: 'https://newexample.com'
                    description: 'The destination URL (writable).'
                    enum: []
                  enabled:
                    type: boolean
                    example: false
                    description: 'Whether the link is enabled (writable).'
                    enum: []
                  hit_count:
                    type: integer
                    example: 42
                    description: 'Total number of times the link has been accessed (read-only).'
                    enum: []
                  http_status_code:
                    type: integer
                    example: 200
                    description: 'HTTP status code from last health check (read-only).'
                    enum: []
                  last_status_check_at:
                    type: string
                    example: '2025-11-21 10:30:00'
                    description: 'Timestamp of last status check (read-only).'
                    enum: []
                  exclude_from_status_check:
                    type: boolean
                    example: true
                    description: 'Whether to exclude from automated health checks (writable, staff only).'
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-01T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-21T12:30:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
                  owner:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                        description: "Owner's user ID (read-only)."
                        enum: []
                      name:
                        type: string
                        example: 'John Doe'
                        description: "Owner's full name (read-only)."
                        enum: []
                      unity_id:
                        type: string
                        example: jdoe
                        description: "Owner's Unity ID (read-only)."
                        enum: []
                    description: 'The link owner details (read-only).'
                  tags:
                    type: array
                    example: []
                    description: 'Associated tags (managed via separate endpoints).'
                    enum: []
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to update this link.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to update this link.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
      tags:
        - Links
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                target_url:
                  type: string
                  description: 'The destination URL.'
                  example: 'https://newexample.com'
                enabled:
                  type: boolean
                  description: 'Whether the link is enabled.'
                  example: false
                exclude_from_status_check:
                  type: boolean
                  description: 'Exclude from status checks (staff only).'
                  example: true
    delete:
      summary: 'Delete Link'
      operationId: deleteLink
      description: 'Delete a link. You must be the owner of the link to delete it.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link deleted successfully.'
                properties:
                  message:
                    type: string
                    example: 'Link deleted successfully.'
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to delete this link. Only the owner can delete links.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to delete this link. Only the owner can delete links.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
      tags:
        - Links
    parameters:
      -
        in: path
        name: string
        description: 'The link string.'
        example: my-link
        required: true
        schema:
          type: string
  '/api/v2/links/{string}/transfer':
    post:
      summary: 'Transfer Link'
      operationId: transferLink
      description: 'Transfer ownership of a link to another user. You must be the owner of the link.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link transferred successfully.'
                  link:
                    id: 1
                    string: my-link
                    target_url: 'https://example.com'
                    owner:
                      id: 2
                      name: 'Jane Smith'
                      unity_id: jsmith
                properties:
                  message:
                    type: string
                    example: 'Link transferred successfully.'
                  link:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      string:
                        type: string
                        example: my-link
                      target_url:
                        type: string
                        example: 'https://example.com'
                      owner:
                        type: object
                        properties:
                          id:
                            type: integer
                            example: 2
                          name:
                            type: string
                            example: 'Jane Smith'
                          unity_id:
                            type: string
                            example: jsmith
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to transfer this link. Only the owner can transfer links.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to transfer this link. Only the owner can transfer links.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The given data was invalid.'
                  errors:
                    new_owner_unity_id:
                      - 'User not found.'
                properties:
                  message:
                    type: string
                    example: 'The given data was invalid.'
                  errors:
                    type: object
                    properties:
                      new_owner_unity_id:
                        type: array
                        example:
                          - 'User not found.'
                        items:
                          type: string
      tags:
        - Links
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                new_owner_unity_id:
                  type: string
                  description: 'The Unity ID of the new owner.'
                  example: jsmith
              required:
                - new_owner_unity_id
    parameters:
      -
        in: path
        name: string
        description: 'The link string.'
        example: my-link
        required: true
        schema:
          type: string
  '/api/v2/links/{string}/tags':
    post:
      summary: 'Attach Tag to Link'
      operationId: attachTagToLink
      description: 'Attach a tag to a link. You must have manage permissions for both the link and the tag.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag attached successfully.'
                  link:
                    id: 1
                    string: my-link
                    tags:
                      -
                        id: 1
                        label: important
                        name: important
                properties:
                  message:
                    type: string
                    example: 'Tag attached successfully.'
                  link:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      string:
                        type: string
                        example: my-link
                      tags:
                        type: array
                        example:
                          -
                            id: 1
                            label: important
                            name: important
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                              example: 1
                            label:
                              type: string
                              example: important
                            name:
                              type: string
                              example: important
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to manage this link or tag.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to manage this link or tag.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The given data was invalid.'
                  errors:
                    tag_id:
                      - 'The tag id field is required.'
                properties:
                  message:
                    type: string
                    example: 'The given data was invalid.'
                  errors:
                    type: object
                    properties:
                      tag_id:
                        type: array
                        example:
                          - 'The tag id field is required.'
                        items:
                          type: string
      tags:
        - Links
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tag_id:
                  type: integer
                  description: 'The tag ID to attach.'
                  example: 1
              required:
                - tag_id
    parameters:
      -
        in: path
        name: string
        description: 'The link string.'
        example: my-link
        required: true
        schema:
          type: string
  '/api/v2/links/{string}/tags/{tag}':
    delete:
      summary: 'Detach Tag from Link'
      operationId: detachTagFromLink
      description: 'Remove a tag from a link. You must have manage permissions for the link.'
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag detached successfully.'
                  link:
                    id: 1
                    string: my-link
                    tags: []
                properties:
                  message:
                    type: string
                    example: 'Tag detached successfully.'
                  link:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 1
                      string:
                        type: string
                        example: my-link
                      tags:
                        type: array
                        example: []
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to manage this link.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to manage this link.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Link not found.'
                properties:
                  message:
                    type: string
                    example: 'Link not found.'
      tags:
        - Links
    parameters:
      -
        in: path
        name: string
        description: 'The link string.'
        example: my-link
        required: true
        schema:
          type: string
      -
        in: path
        name: tag
        description: 'The tag ID to detach.'
        example: 1
        required: true
        schema:
          type: integer
  /api/v2/tags:
    get:
      summary: 'Get Tags'
      operationId: getTags
      description: 'Retrieve all tags owned by the authenticated user.'
      parameters:
        -
          in: query
          name: page
          description: 'Page number for pagination.'
          example: 1
          required: false
          schema:
            type: integer
            description: 'Page number for pagination.'
            example: 1
        -
          in: query
          name: per_page
          description: 'Number of results per page (max 100).'
          example: 15
          required: false
          schema:
            type: integer
            description: 'Number of results per page (max 100).'
            example: 15
        -
          in: query
          name: 'filter[search]'
          description: 'Search in tag labels.'
          example: project
          required: false
          schema:
            type: string
            description: 'Search in tag labels.'
            example: project
        -
          in: query
          name: sort
          description: 'Sort field (label, created_at, updated_at). Default: label.'
          example: label
          required: false
          schema:
            type: string
            description: 'Sort field (label, created_at, updated_at). Default: label.'
            example: label
        -
          in: query
          name: order
          description: 'Sort order (asc, desc). Default: asc.'
          example: asc
          required: false
          schema:
            type: string
            description: 'Sort order (asc, desc). Default: asc.'
            example: asc
        -
          in: query
          name: include_counts
          description: 'Include link counts and hit totals for each tag. Default: false.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Include link counts and hit totals for each tag. Default: false.'
            example: true
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  data:
                    -
                      id: 1
                      label: important
                      name: important
                      created_at: '2025-11-01T12:00:00.000000Z'
                      updated_at: '2025-11-01T12:00:00.000000Z'
                      links_count: 5
                      hits: 142
                    -
                      id: 2
                      label: project-alpha
                      name: project-alpha
                      created_at: '2025-11-02T10:00:00.000000Z'
                      updated_at: '2025-11-02T10:00:00.000000Z'
                      links_count: 12
                      hits: 847
                  meta:
                    current_page: 1
                    per_page: 15
                    total: 2
                    last_page: 1
                properties:
                  data:
                    type: array
                    example:
                      -
                        id: 1
                        label: important
                        name: important
                        created_at: '2025-11-01T12:00:00.000000Z'
                        updated_at: '2025-11-01T12:00:00.000000Z'
                        links_count: 5
                        hits: 142
                      -
                        id: 2
                        label: project-alpha
                        name: project-alpha
                        created_at: '2025-11-02T10:00:00.000000Z'
                        updated_at: '2025-11-02T10:00:00.000000Z'
                        links_count: 12
                        hits: 847
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        label:
                          type: string
                          example: important
                        name:
                          type: string
                          example: important
                        created_at:
                          type: string
                          example: '2025-11-01T12:00:00.000000Z'
                        updated_at:
                          type: string
                          example: '2025-11-01T12:00:00.000000Z'
                        links_count:
                          type: integer
                          example: 5
                        hits:
                          type: integer
                          example: 142
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                        example: 1
                      per_page:
                        type: integer
                        example: 15
                      total:
                        type: integer
                        example: 2
                      last_page:
                        type: integer
                        example: 1
        401:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: Unauthenticated.
                properties:
                  message:
                    type: string
                    example: Unauthenticated.
      tags:
        - Tags
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                  description: 'Must be at least 1. Must not be greater than 100.'
                  example: 1
                filter:
                  type: object
                  description: ''
                  example: []
                  properties:
                    search:
                      type: string
                      description: ''
                      example: architecto
                sort:
                  type: string
                  description: ''
                  example: null
                order:
                  type: string
                  description: ''
                  example: null
                include_counts:
                  type: boolean
                  description: ''
                  example: true
    post:
      summary: 'Create Tag'
      operationId: createTag
      description: 'Create a new tag for organizing your links.'
      parameters: []
      responses:
        201:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  label: 'My Project'
                  name: my-project
                  user_id: 1
                  created_at: '2025-11-21T12:00:00.000000Z'
                  updated_at: '2025-11-21T12:00:00.000000Z'
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique tag identifier (read-only).'
                    enum: []
                  label:
                    type: string
                    example: 'My Project'
                    description: 'The tag display label (writable).'
                    enum: []
                  name:
                    type: string
                    example: my-project
                    description: 'The tag slug name, auto-generated from label (read-only).'
                    enum: []
                  user_id:
                    type: integer
                    example: 1
                    description: "The tag owner's user ID (read-only)."
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-21T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-21T12:00:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
        422:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'The given data was invalid.'
                  errors:
                    label:
                      - 'The label field is required.'
                properties:
                  message:
                    type: string
                    example: 'The given data was invalid.'
                  errors:
                    type: object
                    properties:
                      label:
                        type: array
                        example:
                          - 'The label field is required.'
                        items:
                          type: string
      tags:
        - Tags
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  description: 'The tag label (will be slugified).'
                  example: 'My Project'
              required:
                - label
  '/api/v2/tags/{id}':
    get:
      summary: 'Get Tag'
      operationId: getTag
      description: 'Retrieve a specific tag by ID.'
      parameters:
        -
          in: query
          name: include_links
          description: 'Include all links with this tag. Default: false.'
          example: true
          required: false
          schema:
            type: boolean
            description: 'Include all links with this tag. Default: false.'
            example: true
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  label: important
                  name: important
                  user_id: 1
                  created_at: '2025-11-01T12:00:00.000000Z'
                  updated_at: '2025-11-01T12:00:00.000000Z'
                  links_count: 5
                  hits: 142
                  links:
                    -
                      id: 1
                      string: example
                      target_url: 'https://example.com'
                      enabled: true
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique tag identifier (read-only).'
                    enum: []
                  label:
                    type: string
                    example: important
                    description: 'The tag display label (writable).'
                    enum: []
                  name:
                    type: string
                    example: important
                    description: 'The tag slug name, auto-generated from label (read-only).'
                    enum: []
                  user_id:
                    type: integer
                    example: 1
                    description: "The tag owner's user ID (read-only)."
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-01T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-01T12:00:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
                  links_count:
                    type: integer
                    example: 5
                    description: 'Number of links tagged with this tag (read-only).'
                    enum: []
                  hits:
                    type: integer
                    example: 142
                    description: 'Total hits across all links with this tag (read-only).'
                    enum: []
                  links:
                    type: array
                    example:
                      -
                        id: 1
                        string: example
                        target_url: 'https://example.com'
                        enabled: true
                    description: 'Associated links (read-only, only when include_links=true).'
                    enum: []
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 1
                        string:
                          type: string
                          example: example
                        target_url:
                          type: string
                          example: 'https://example.com'
                        enabled:
                          type: boolean
                          example: true
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to view this tag.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to view this tag.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag not found.'
                properties:
                  message:
                    type: string
                    example: 'Tag not found.'
      tags:
        - Tags
    patch:
      summary: 'Update Tag'
      operationId: updateTag
      description: "Update a tag's label. You must be the owner of the tag."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  id: 1
                  label: 'Updated Project'
                  name: updated-project
                  user_id: 1
                  created_at: '2025-11-01T12:00:00.000000Z'
                  updated_at: '2025-11-21T12:30:00.000000Z'
                properties:
                  id:
                    type: integer
                    example: 1
                    description: 'The unique tag identifier (read-only).'
                    enum: []
                  label:
                    type: string
                    example: 'Updated Project'
                    description: 'The tag display label (writable).'
                    enum: []
                  name:
                    type: string
                    example: updated-project
                    description: 'The tag slug name, auto-generated from label (read-only).'
                    enum: []
                  user_id:
                    type: integer
                    example: 1
                    description: "The tag owner's user ID (read-only)."
                    enum: []
                  created_at:
                    type: string
                    example: '2025-11-01T12:00:00.000000Z'
                    description: 'Creation timestamp (read-only).'
                    enum: []
                  updated_at:
                    type: string
                    example: '2025-11-21T12:30:00.000000Z'
                    description: 'Last modification timestamp (read-only).'
                    enum: []
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to update this tag.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to update this tag.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag not found.'
                properties:
                  message:
                    type: string
                    example: 'Tag not found.'
      tags:
        - Tags
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  description: 'The new tag label.'
                  example: 'Updated Project'
              required:
                - label
    delete:
      summary: 'Delete Tag'
      operationId: deleteTag
      description: "Delete a tag. This will automatically detach the tag from all associated links.\nYou must be the owner of the tag."
      parameters: []
      responses:
        200:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag deleted successfully. The tag was removed from 5 link(s).'
                properties:
                  message:
                    type: string
                    example: 'Tag deleted successfully. The tag was removed from 5 link(s).'
        403:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'You do not have permission to delete this tag.'
                properties:
                  message:
                    type: string
                    example: 'You do not have permission to delete this tag.'
        404:
          description: ''
          content:
            application/json:
              schema:
                type: object
                example:
                  message: 'Tag not found.'
                properties:
                  message:
                    type: string
                    example: 'Tag not found.'
      tags:
        - Tags
    parameters:
      -
        in: path
        name: id
        description: 'The ID of the tag.'
        example: architecto
        required: true
        schema:
          type: string
      -
        in: path
        name: tag
        description: 'The tag ID.'
        example: 1
        required: true
        schema:
          type: integer
