Taskfolk API

First-party REST API (~180 operations) covering issues, projects, sprints, comments, agents, docs, goals, forms, automations, chat, and webhooks. Bearer API key auth, cursor pagination, signed webhooks. Also exposes a hosted MCP server over Streamable HTTP.

Documentation

Specifications

Other Resources

🔗
DeveloperPortal
https://taskfolk.ai/developer
🔗
MCPServer
https://taskfolk.ai/api/mcp/v1
🔗
MCPServer
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/mcp/taskfolk-mcp.yml
🔗
ToolCrosswalk
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/mcp/taskfolk-tool-crosswalk.yml
🔗
AgentCard
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/a2a/taskfolk-a2a.yml
🔗
OAuthScopes
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/scopes/taskfolk-scopes.yml
🔗
Webhooks
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/asyncapi/taskfolk-webhooks.yml
🔗
ErrorCatalog
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/errors/taskfolk-problem-types.yml
🔗
Conventions
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/conventions/taskfolk-conventions.yml
🔗
Idempotency
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/conventions/taskfolk-conventions.yml
🔗
DataModel
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/data-model/taskfolk-data-model.yml
🔗
Overlay
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/overlays/taskfolk-product-api-overlay.yaml
🔗
AgentSkill
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/skills/_index.yml
🔗
APIsJSON
https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/apis.yml

OpenAPI Specification

taskfolk-product-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Taskfolk API
  version: 1.0.0
  description: Public REST API for Taskfolk (taskfolk.ai). All endpoints require a workspace-scoped bearer API key. Paths
    are nested under `/v1/workspaces/{slug}/…`.
servers:
- url: https://taskfolk.ai/api
security:
- bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: 'Workspace API key. Send as `Authorization: Bearer tfk_live_…`. Each key is bound to exactly one workspace
        and carries a set of scopes.'
  schemas:
    ErrorEnvelope:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
              - unauthorized
              - forbidden
              - not_found
              - validation
              - rate_limited
              - conflict
              - idempotency_violation
              - internal_error
              example: validation
            message:
              type: string
              example: Label "foo" does not exist on this project.
            details:
              type: object
              additionalProperties: {}
          required:
          - code
          - message
      required:
      - error
    Workspace:
      type: object
      properties:
        id:
          type: string
        slug:
          type: string
          example: taskfolk
        name:
          type: string
          example: Taskfolk
        default_locale:
          type: string
          example: en
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - slug
      - name
      - default_locale
      - created_at
    WorkspacePatchInput:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
          example: Taskfolk
      required:
      - name
    Project:
      type: object
      properties:
        id:
          type: string
        key:
          type: string
          example: WEB
        slug:
          type: string
          example: web
        name:
          type: string
          example: Website
        description_md:
          type:
          - string
          - 'null'
        lead_user_id:
          type:
          - string
          - 'null'
        scoped:
          type: boolean
          description: True when access is restricted to explicit project members.
        estimation_unit:
          type: string
          enum:
          - time
          - points
          - none
          description: 'How this project estimates work (POINTS-01): time (estimate_minutes), points (story_points), or none.'
        archived_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - key
      - slug
      - name
      - description_md
      - lead_user_id
      - scoped
      - estimation_unit
      - archived_at
      - created_at
      - updated_at
    Label:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: frontend
        color:
          type: string
          example: '#f5c518'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - name
      - color
      - created_at
    ProjectStatus:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: In Review
        name_ar:
          type:
          - string
          - 'null'
          example: قيد المراجعة
        color:
          type: string
          example: '#4FE8E5'
        category:
          type: string
          enum:
          - backlog
          - todo
          - in_progress
          - in_review
          - done
          - failed
          - cancelled
          description: System category the status maps to (open/done semantics).
        rank:
          type: string
          description: LexoRank ordering string.
      required:
      - id
      - name
      - name_ar
      - color
      - category
      - rank
    Issue:
      type: object
      properties:
        id:
          type: string
        key:
          type: string
          example: WEB-39
        url:
          type: string
          example: https://taskfolk.ai/w/taskfolk/p/web/WEB-39
        number:
          type: integer
        type:
          type: string
          enum:
          - epic
          - story
          - task
          - bug
          - subtask
        title:
          type: string
        description_md:
          type:
          - string
          - 'null'
        status:
          type: string
          enum:
          - backlog
          - todo
          - in_progress
          - in_review
          - done
          - failed
          - cancelled
        status_id:
          type:
          - string
          - 'null'
          description: Specific board status id (project_statuses). See GET .../statuses.
        status_name:
          type:
          - string
          - 'null'
          description: Display name of the board status.
        priority:
          type: string
          enum:
          - lowest
          - low
          - medium
          - high
          - highest
          - critical
        assignee_id:
          type:
          - string
          - 'null'
          description: Primary assignee (compat). Equals assignees[0], or null when unassigned.
        assignees:
          type: array
          items:
            type: string
          description: All assignee user ids, primary first. Set via PATCH assignee_ids.
        reporter_id:
          type: string
        parent_id:
          type:
          - string
          - 'null'
        epic_id:
          type:
          - string
          - 'null'
        milestone_id:
          type:
          - string
          - 'null'
          description: Attached milestone id, or null.
        sprint_id:
          type:
          - string
          - 'null'
          description: Attached sprint id, or null.
        release_id:
          type:
          - string
          - 'null'
          description: Attached release id, or null.
        labels:
          type: array
          items:
            $ref: '#/components/schemas/Label'
        estimate_minutes:
          type:
          - integer
          - 'null'
        story_points:
          type:
          - integer
          - 'null'
          description: Story points estimate (POINTS-01); used when the project's estimation_unit is "points". Null = unestimated.
        spent_minutes:
          type:
          - integer
          - 'null'
        completion_pct:
          type:
          - integer
          - 'null'
        start_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        due_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        resolved_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        archived_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - key
      - url
      - number
      - type
      - title
      - description_md
      - status
      - status_id
      - status_name
      - priority
      - assignee_id
      - assignees
      - reporter_id
      - parent_id
      - epic_id
      - milestone_id
      - sprint_id
      - release_id
      - labels
      - estimate_minutes
      - story_points
      - spent_minutes
      - completion_pct
      - start_at
      - due_at
      - resolved_at
      - archived_at
      - created_at
      - updated_at
    Comment:
      type: object
      properties:
        id:
          type: string
        issue_id:
          type: string
        author_id:
          type: string
        body_md:
          type: string
        body_html:
          type: string
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - issue_id
      - author_id
      - body_md
      - body_html
      - created_at
      - updated_at
    Activity:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          example: status_changed
        actor_id:
          type:
          - string
          - 'null'
        payload:
          type: object
          additionalProperties: {}
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - kind
      - actor_id
      - payload
      - created_at
    Watcher:
      type: object
      properties:
        user_id:
          type: string
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - user_id
      - created_at
    Attachment:
      type: object
      properties:
        id:
          type: string
        issue_id:
          type: string
        comment_id:
          type:
          - string
          - 'null'
        file_name:
          type: string
        mime:
          type: string
        byte_size:
          type: integer
        uploader_id:
          type: string
        url:
          type:
          - string
          - 'null'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - issue_id
      - comment_id
      - file_name
      - mime
      - byte_size
      - uploader_id
      - url
      - created_at
    UploadIntent:
      type: object
      properties:
        r2_key:
          type: string
        url:
          type: string
          description: Pre-signed R2 PUT URL.
        relay_url:
          type: string
          description: Same-origin fallback PUT path for networks that block the storage domain. PUT the same bytes here if
            the direct URL is unreachable.
        headers:
          type: object
          additionalProperties:
            type: string
        expires_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - r2_key
      - url
      - relay_url
      - headers
      - expires_at
    CustomFieldDef:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: severity
        kind:
          type: string
          enum:
          - text
          - number
          - select
          - multi_select
          - date
          - checkbox
          - url
          - user
          - project
          - doc
        options:
          type: array
          items:
            type: string
        applies_to:
          type: array
          items:
            type: string
            enum:
            - epic
            - story
            - task
            - bug
            - subtask
        required:
          type: boolean
        rank:
          type: string
      required:
      - id
      - name
      - kind
      - options
      - applies_to
      - required
      - rank
    CustomFieldValue:
      type: object
      properties:
        field_id:
          type: string
        name:
          type: string
        kind:
          type: string
        value: {}
      required:
      - field_id
    Sprint:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: Sprint 7
        goal:
          type:
          - string
          - 'null'
          description: Sprint goal (markdown).
        status:
          type: string
          enum:
          - planned
          - active
          - completed
        start_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        end_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        rank:
          type: string
      required:
      - id
      - name
      - goal
      - status
      - start_at
      - end_at
      - rank
    Milestone:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: v2.0 Release
        description_md:
          type:
          - string
          - 'null'
          description: Milestone description (markdown).
        status:
          type: string
          enum:
          - planned
          - active
          - completed
        start_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        due_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        rank:
          type: string
      required:
      - id
      - name
      - description_md
      - status
      - start_at
      - due_at
      - rank
    Release:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: Autumn Launch
        version:
          type:
          - string
          - 'null'
          example: 2.1.0
          description: Semantic version or build tag.
        description_md:
          type:
          - string
          - 'null'
          description: Release notes (markdown).
        status:
          type: string
          enum:
          - planned
          - in_progress
          - released
          - cancelled
        target_date:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
          description: Planned ship date.
        released_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
          description: Actual ship time; set when status becomes released.
        rank:
          type: string
      required:
      - id
      - name
      - version
      - description_md
      - status
      - target_date
      - released_at
      - rank
    Report:
      type: object
      properties:
        report:
          type: string
          enum:
          - velocity
          - burndown
          - cycle-time
          - throughput
          - status-breakdown
          - type-breakdown
          - workload
          description: Which report this payload describes.
        data:
          description: 'Report-specific payload. Shape depends on `report`: velocity (bars + average), burndown (points),
            cycle-time (buckets + percentiles), throughput (weekly created vs resolved), status/type-breakdown (slices), workload
            (rows by assignee). Sprint-dependent reports may be null when the project has no sprints.'
      required:
      - report
    SavedView:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        filter:
          description: Opaque filter blob (issueTypes[], priorities[], assigneeId, sort…).
        is_shared:
          type: boolean
        created_by:
          type: string
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - name
      - is_shared
      - created_by
      - created_at
      - updated_at
    TimeTracking:
      type: object
      properties:
        issue_key:
          type: string
          example: WEB-12
        estimate_minutes:
          type:
          - integer
          - 'null'
        story_points:
          type:
          - integer
          - 'null'
        spent_minutes:
          type:
          - integer
          - 'null'
        completion_pct:
          type:
          - integer
          - 'null'
      required:
      - issue_key
      - estimate_minutes
      - story_points
      - spent_minutes
      - completion_pct
    IssueLink:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          enum:
          - relates_to
          - blocks
          - duplicates
        direction:
          type: string
          enum:
          - out
          - in
          description: '"out" = anchor → target, "in" = target → anchor.'
        target_key:
          type: string
          example: WEB-12
        target_title:
          type: string
        target_status:
          type: string
        target_project_slug:
          type: string
      required:
      - id
      - kind
      - direction
      - target_key
      - target_title
      - target_status
      - target_project_slug
    CommitRef:
      type: object
      properties:
        id:
          type: string
        repo:
          type: string
          example: utter-ae/product
        sha:
          type: string
          example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
        message:
          type: string
        url:
          type: string
          example: https://github.com/utter-ae/product/commit/a1b2c3
        author:
          type:
          - string
          - 'null'
        committed_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - repo
      - sha
      - message
      - url
      - author
      - committed_at
    Doc:
      type: object
      properties:
        id:
          type: string
        title:
          type: string
        project_id:
          type:
          - string
          - 'null'
        parent_id:
          type:
          - string
          - 'null'
        icon:
          type:
          - string
          - 'null'
        body_md:
          type:
          - string
          - 'null'
        body_json: {}
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - title
      - project_id
      - parent_id
      - icon
      - body_md
      - created_at
      - updated_at
    Member:
      type: object
      properties:
        user_id:
          type: string
        email:
          type: string
        name:
          type:
          - string
          - 'null'
        role:
          type: string
          enum:
          - owner
          - admin
          - member
          - viewer
      required:
      - user_id
      - email
      - name
      - role
    Invite:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
          example: user@example.com
        role:
          type: string
          enum:
          - admin
          - member
          - viewer
          - guest
        invited_by_user_id:
          type: string
        expires_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - email
      - role
      - invited_by_user_id
      - expires_at
      - created_at
    InviteCreateInput:
      type: object
      properties:
        email:
          type: string
          format: email
          example: user@example.com
        role:
          type: string
          enum:
          - admin
          - member
          - viewer
          - guest
      required:
      - email
      - role
    ProjectMember:
      type: object
      properties:
        user_id:
          type: string
        email:
          type: string
        name:
          type:
          - string
          - 'null'
        role:
          type: string
          enum:
          - admin
          - member
          - viewer
        added_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - user_id
      - email
      - name
      - role
      - added_at
    ProjectMemberAddInput:
      type: object
      properties:
        user_id:
          type: string
          description: ID of an existing workspace member.
        role:
          type: string
          enum:
          - admin
          - member
          - viewer
      required:
      - user_id
      - role
    MemberPatchInput:
      type: object
      properties:
        role:
          type: string
          enum:
          - admin
          - member
          - viewer
          description: New role for the member. Cannot promote to owner; use the ownership-transfer flow.
      required:
      - role
    Notification:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          example: assigned
        read_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - kind
      - read_at
      - created_at
    SearchResult:
      type: object
      properties:
        type:
          type: string
          enum:
          - issue
          - doc
        id:
          type: string
        title:
          type: string
        url:
          type:
          - string
          - 'null'
      required:
      - type
      - id
      - title
    Me:
      type: object
      properties:
        keyId:
          type: string
        name:
          type: string
        workspaceSlug:
          type: string
        scopes:
          type: array
          items:
            type: string
        expiresAt:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - keyId
      - name
      - workspaceSlug
      - scopes
      - expiresAt
    ApiKey:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          example: CI deploy bot
        prefix:
          type: string
          example: tfk_live_abcd
        scopes:
          type: array
          items:
            type: string
          example:
          - issues:read
          - issues:write
        project_ids:
          type:
          - array
          - 'null'
          items:
            type: string
        rate_limit_per_minute:
          type:
          - integer
          - 'null'
        created_by:
          type: string
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
        expires_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        last_used_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        last_used_ip:
          type:
          - string
          - 'null'
        revoked_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        revoke_reason:
          type:
          - string
          - 'null'
      required:
      - id
      - name
      - prefix
      - scopes
      - project_ids
      - rate_limit_per_minute
      - created_by
      - created_at
      - expires_at
      - last_used_at
      - last_used_ip
      - revoked_at
      - revoke_reason
    CreatedApiKey:
      allOf:
      - $ref: '#/components/schemas/ApiKey'
      - type: object
        properties:
          plaintext:
            type: string
            example: tfk_live_abcd1234...
            description: Returned exactly once on create. Store it securely.
        required:
        - plaintext
    Webhook:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
          example: https://example.com/taskfolk/webhook
        event_types:
          type: array
          items:
            type: string
          example:
          - issue.created
          - comment.created
        secret_prefix:
          type: string
        disabled_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        last_delivery_at:
          type:
          - string
          - 'null'
          format: date-time
          example: '2026-05-28T14:30:00Z'
        last_delivery_status:
          type:
          - integer
          - 'null'
        created_by:
          type: string
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - id
      - url
      - event_types
      - secret_prefix
      - disabled_at
      - last_delivery_at
      - last_delivery_status
      - created_by
      - created_at
    CreatedWebhook:
      allOf:
      - $ref: '#/components/schemas/Webhook'
      - type: object
        properties:
          secret:
            type: string
            example: utwhsec_...
            description: Returned exactly once on create or rotation.
        required:
        - secret
    WebhookDelivery:
      type: object
      properties:
        delivery_id:
          type: string
        event_type:
          type: string
          example: webhook.test
        attempt:
          type: integer
          example: 1
        status:
          type: integer
          example: 200
        latency_ms:
          type: integer
          example: 123
        error:
          type: string
        final:
          type: integer
          example: 1
        ts:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - delivery_id
      - event_type
      - attempt
      - status
      - latency_ms
      - error
      - final
      - ts
    ApiKeyUsageDayPoint:
      type: object
      properties:
        date:
          type: string
          example: '2026-06-15'
        requests:
          type: integer
        errors:
          type: integer
        p50_ms:
          type: integer
        p95_ms:
          type: integer
        p99_ms:
          type: integer
      required:
      - date
      - requests
      - errors
      - p50_ms
      - p95_ms
      - p99_ms
    ApiKeyUsage:
      type: object
      properties:
        key_id:
          type: string
        from:
          type: string
          example: '2026-05-17'
        to:
          type: string
          example: '2026-06-15'
        granularity:
          type: string
          enum:
          - day
        series:
          type: array
          items:
            $ref: '#/components/schemas/ApiKeyUsageDayPoint'
        totals:
          type: object
          properties:
            requests:
              type: integer
            errors:
              type: integer
            p95_ms:
              type: integer
          required:
          - requests
          - errors
          - p95_ms
      required:
      - key_id
      - from
      - to
      - granularity
      - series
      - totals
    OauthApp:
      type: object
      properties:
        client_id:
          type: string
          example: utoc_...
        name:
          type: string
          example: My CI Integration
        redirect_uris:
          type: array
          items:
            type: string
            format: uri
          example:
          - https://example.com/callback
        scopes:
          type: array
          items:
            type: string
          example:
          - issues:read
          - comments:write
        is_public:
          type: boolean
          description: True = PKCE public client (no secret).
        created_at:
          type: string
          format: date-time
          example: '2026-05-28T14:30:00Z'
      required:
      - client_id
      - name
      - redirect_uris
      - scopes
      - is_public
      - created_at
    CreatedOauthApp:
      allOf:
      - $ref: '#/components/schemas/OauthApp'
      - type: object
        properties:
          client_secret:
            type:
            - string
            - 'null'
            example: utos_...
            description: Returned exactly once on create. Null for public (PKCE) clients.
        required:
        - client_secret
    OauthAppCreateInput:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 120
          example: My CI Integration
        redirect_uris:
          type: array
          items:
            type: string
            format: uri
          minItems: 1
          maxItems: 20
          example:
          - https://example.com/callback
        scopes:
          type: array
          items:
            type: string
          minItems: 1
          example:
          - issues:read
        is_public:
          type: boolean
          description: Set true for PKCE public clients (no secret).
          example: false
      required:
      - name
      - redirect_uris
      - scopes
    ProjectCreateInput:
      type: object
      properties:
        key:
          type: string
          example: WEB
        name:
          type: string
        slug:
          type: string
        description_md:
          type: string
        lead_user_id:
          type: string
      required:
      - key
      - name
    ProjectPatchInput:
      type: object
      properties:
        name:
          type: string
        description_md:
          type:
          - string
          - 'null'
        lead_user_id:
          type:
          - string
          - 'null'
        estimation_unit:
          type: string
          enum:
          - time
          - points
          - none
    IssueCreateInput:
      type: object
      properties:
        type:
          type: string
          enum:
          - epic
          - story
          - task
          - bug
          - subtask
        title:
          type: string
        description_md:
          type: string
        status:
          type: string
          enum:
          - backlog
          - todo
          - in_progress
          - in_review
          - done
          - failed
          - cancelled
        status_id:
          type: string
          description: Board status id (project_statuses); wins over status.
        priority:
          type: string
          enum:
          - lowest
          - low
          - medium
          - high
          - highest
          - critical
        assignee:
          type: string
          description: user_id or email
          example: omar@haris.bz
        labels:
          type: array
          items:
            type: string
          description: label ids or names
        parent:
          type: string
          example: WEB-2
        epic:
          type: string
          example: WEB-2
        start_at:
          type:
          - string
          - 'null'
        due_at:
          type:
          - string
          - 'null'
        estimate_minutes:
          type:
          - integer
          - 'null'
        story_points:
          type:
          - integer
          - 'null'
      requ

# --- truncated at 32 KB (508 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/taskfolk/refs/heads/main/openapi/taskfolk-product-api-openapi.yml