--- openapi: 3.1.0 info: title: WIP API version: 1.2.0 description: | The WIP REST API lets you read and write todos, projects, comments, and reactions. ## Access All endpoints require an active subscription. Accounts without access receive a 401 response with an upgrade URL. ## Expanding responses Some responses can include related records inline on request, similar to Stripe's `expand`. Pass `expand` as a query parameter with a comma-separated list (`?expand=reactions`) or the repeated array form (`?expand[]=reactions`). Expandable fields are omitted by default to keep base payloads small. See each endpoint's parameters for the values it supports. ## API keys API keys can be **read-write** (default) or **read-only**. Read-only keys can fetch data but cannot create, update, or delete resources (403 Forbidden). OAuth 2.0 access tokens are an alternative to API keys for third-party applications. license: name: MIT url: https://opensource.org/licenses/MIT servers: - url: https://api.wip.co security: - ApiKeyHeader: [] - ApiKeyQuery: [] - OAuth2: [] tags: - name: Todos description: Operations for managing todos - name: Users description: Operations for managing users - name: Projects description: Operations for managing projects - name: Uploads description: Operations for managing file uploads - name: Viewer description: Operations for the currently authenticated user - name: Reactions description: Operations for managing reactions (likes) on resources - name: Comments description: Operations for managing comments on resources - name: Webhooks description: Operations for managing webhook subscriptions - name: Moderation description: Operations for reporting content and blocking users - name: Following description: Operations for following and unfollowing users and projects - name: Account description: Operations for managing the authenticated user's account paths: "/v1/todos": post: tags: - Todos summary: Create a completed todo operationId: createTodo requestBody: required: true content: application/json: schema: type: object properties: body: type: string description: The content of the todo attachments: type: array items: type: string description: List of attachment signed IDs required: - body responses: '201': description: Created todo content: application/json: schema: "$ref": "#/components/schemas/Todo" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/todos/{todo_id}": get: tags: - Todos summary: Return a single (completed) todo operationId: getTodo parameters: - "$ref": "#/components/parameters/TodoIdParam" - "$ref": "#/components/parameters/ExpandReactionsParam" responses: '200': description: A single (completed) todo content: application/json: schema: "$ref": "#/components/schemas/Todo" '404': description: Not found patch: tags: - Todos summary: Update a todo description: Update the body text or attachments for one of your own todos. Attachments are additive; use remove_attachment_ids to delete existing attachments from the todo. operationId: updateTodo parameters: - "$ref": "#/components/parameters/TodoIdParam" requestBody: required: true content: application/json: schema: type: object properties: body: type: string description: The new content of the todo attachments: type: array items: type: string description: List of attachment signed IDs to add to the todo remove_attachment_ids: type: array items: type: string description: List of existing todo attachment IDs to remove responses: '200': description: Todo updated successfully content: application/json: schema: "$ref": "#/components/schemas/Todo" '403': description: Forbidden — read-only API key, or you can only update your own todos content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Todo not found '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/todos/{todo_id}/comments": get: tags: - Todos - Comments summary: Return all comments for a todo operationId: getTodoComments parameters: - "$ref": "#/components/parameters/TodoIdParam" - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" responses: '200': description: A list of comments for the todo content: application/json: schema: "$ref": "#/components/schemas/PaginatedComments" '404': description: Todo not found "/v1/users/{username}": get: tags: - Users summary: Return a single user operationId: getUser parameters: - "$ref": "#/components/parameters/UsernameParam" responses: '200': description: A single user content: application/json: schema: "$ref": "#/components/schemas/User" '404': description: Not found "/v1/users/{username}/projects": get: tags: - Users - Projects summary: Return all projects for a user operationId: getUserProjects parameters: - "$ref": "#/components/parameters/UsernameParam" - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" responses: '200': description: A list of projects content: application/json: schema: "$ref": "#/components/schemas/PaginatedProjects" '404': description: Not found "/v1/users/{username}/todos": get: tags: - Users - Todos summary: Return all (completed) todos for a user operationId: getUserTodos parameters: - "$ref": "#/components/parameters/UsernameParam" - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" - "$ref": "#/components/parameters/SinceParam" - "$ref": "#/components/parameters/UntilParam" - "$ref": "#/components/parameters/QueryParam" - "$ref": "#/components/parameters/ExpandReactionsParam" responses: '200': description: A list of (completed) todos content: application/json: schema: "$ref": "#/components/schemas/PaginatedTodos" '400': description: Invalid date format for since or until parameter content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Not found "/v1/projects/{project_id}": get: tags: - Projects summary: Return a single project operationId: getProject parameters: - "$ref": "#/components/parameters/ProjectIdParam" responses: '200': description: A single project content: application/json: schema: "$ref": "#/components/schemas/Project" '404': description: Not found "/v1/projects/{project_id}/todos": get: tags: - Projects - Todos summary: Return all (completed) todos for a project operationId: getProjectTodos parameters: - "$ref": "#/components/parameters/ProjectIdParam" - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" - "$ref": "#/components/parameters/SinceParam" - "$ref": "#/components/parameters/UntilParam" - "$ref": "#/components/parameters/QueryParam" - "$ref": "#/components/parameters/ExpandReactionsParam" responses: '200': description: A list of (completed) todos content: application/json: schema: "$ref": "#/components/schemas/PaginatedTodos" '400': description: Invalid date format for since or until parameter content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Not found "/v1/uploads": post: tags: - Uploads summary: Request pre-signed URL for direct file upload description: | Get a pre-signed URL and credentials to upload a file directly to storage (R2/S3). Steps: 1. Call this endpoint for upload credentials 2. Upload file to returned `url` with PUT request, including provided `headers` Use returned `signed_id` to attach file to other resources. operationId: createUpload requestBody: required: true content: application/json: schema: type: object properties: filename: type: string description: Name of the file to upload byte_size: type: integer description: Size of the file in bytes checksum: type: string description: MD5 checksum of the file content_type: type: string description: MIME type of the file required: - filename - byte_size - checksum - content_type responses: '200': description: | Upload credentials generated successfully. Use this response to perform the actual file upload to storage. content: application/json: schema: "$ref": "#/components/schemas/Upload" '400': description: Invalid input "/v1/reactions": post: tags: - Reactions summary: Create a reaction on a resource description: | Add a reaction (like) to a todo or comment. If the user has already reacted with the same type, the existing reaction is returned. operationId: createReaction requestBody: required: true content: application/json: schema: type: object properties: reactable_type: type: string enum: - Todo - Comment description: The type of resource to react to reactable_id: type: string description: The ID of the resource to react to (`todo_` or `comm_` prefix ID). required: - reactable_type - reactable_id responses: '201': description: Reaction created successfully content: application/json: schema: "$ref": "#/components/schemas/Reaction" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/reactions/{reaction_id}": delete: tags: - Reactions summary: Delete a reaction description: Remove your reaction from a resource. You can only delete your own reactions. operationId: deleteReaction parameters: - "$ref": "#/components/parameters/ReactionIdParam" responses: '204': description: Reaction deleted successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Reaction not found "/v1/comments": post: tags: - Comments summary: Create a comment on a resource description: Add a comment to a todo. operationId: createComment requestBody: required: true content: application/json: schema: type: object properties: commentable_type: type: string enum: - Todo description: The type of resource to comment on commentable_id: type: string description: The ID of the resource to comment on (`todo_` prefix ID). body: type: string description: The content of the comment required: - commentable_type - commentable_id - body responses: '201': description: Comment created successfully content: application/json: schema: "$ref": "#/components/schemas/Comment" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/comments/{comment_id}": patch: tags: - Comments summary: Update a comment description: Update your own comment. You can only update comments you created. operationId: updateComment parameters: - "$ref": "#/components/parameters/CommentIdParam" requestBody: required: true content: application/json: schema: type: object properties: body: type: string description: The new content of the comment required: - body responses: '200': description: Comment updated successfully content: application/json: schema: "$ref": "#/components/schemas/Comment" '403': description: Forbidden — read-only API key, or you can only update your own comments content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Comment not found '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" delete: tags: - Comments summary: Delete a comment description: Delete your own comment. You can only delete comments you created. operationId: deleteComment parameters: - "$ref": "#/components/parameters/CommentIdParam" responses: '204': description: Comment deleted successfully '403': description: Forbidden — read-only API key, or you can only delete your own comments content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Comment not found "/v1/reports": post: tags: - Moderation summary: Report a resource description: | Report a todo, comment, or user for review by the WIP team. Used to flag objectionable content or abusive behavior. operationId: createReport requestBody: required: true content: application/json: schema: type: object properties: reportable_type: type: string enum: - Todo - Comment - User description: The type of resource to report reportable_id: type: string description: The ID of the resource to report (`todo_`, `comm_`, or `user_` prefix ID). required: - reportable_type - reportable_id responses: '201': description: Report created successfully content: application/json: schema: "$ref": "#/components/schemas/Report" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/users/{user_id}/mute": post: tags: - Moderation summary: Block (mute) a user description: | Block a user so their todos and comments no longer appear in your timeline. Idempotent — blocking an already-blocked user succeeds. operationId: muteUser parameters: - "$ref": "#/components/parameters/UserIdParam" responses: '204': description: User blocked successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: User not found delete: tags: - Moderation summary: Unblock (unmute) a user description: Remove a block you previously placed on a user. operationId: unmuteUser parameters: - "$ref": "#/components/parameters/UserIdParam" responses: '204': description: User unblocked successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: User not found "/v1/users/{user_id}/follow": post: tags: - Following summary: Follow a user description: | Follow a user so their activity appears in your following timeline. Idempotent — following an already-followed user succeeds. operationId: followUser parameters: - "$ref": "#/components/parameters/UserIdParam" responses: '204': description: User followed successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: User not found delete: tags: - Following summary: Unfollow a user description: Stop following a user you previously followed. Idempotent. operationId: unfollowUser parameters: - "$ref": "#/components/parameters/UserIdParam" responses: '204': description: User unfollowed successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: User not found "/v1/projects/{project_id}/follow": post: tags: - Following summary: Follow a project description: | Follow a project so its activity appears in your following timeline. Idempotent — following an already-followed project succeeds. operationId: followProject parameters: - "$ref": "#/components/parameters/ProjectIdParam" responses: '204': description: Project followed successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Project not found delete: tags: - Following summary: Unfollow a project description: Stop following a project you previously followed. Idempotent. operationId: unfollowProject parameters: - "$ref": "#/components/parameters/ProjectIdParam" responses: '204': description: Project unfollowed successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Project not found "/v1/account": delete: tags: - Account summary: Delete the authenticated user's account description: | Schedule the authenticated user's account for permanent deletion. The request is reviewed by the WIP team before the account and its data are removed. operationId: deleteAccount responses: '204': description: Account deletion requested successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/webhooks/subscriptions": get: tags: - Webhooks summary: List webhook subscriptions description: Return all webhook subscriptions belonging to the authenticated user. operationId: getWebhookSubscriptions responses: '200': description: A list of webhook subscriptions content: application/json: schema: type: array items: "$ref": "#/components/schemas/WebhookSubscription" post: tags: - Webhooks summary: Create a webhook subscription description: | Subscribe to an event. We'll send a POST request to the given URL whenever the event occurs. Optionally scope the subscription to specific projects. operationId: createWebhookSubscription requestBody: required: true content: application/json: schema: type: object properties: url: type: string description: The URL we'll send the POST request to. event_type: type: string enum: - new_todo description: The event to subscribe to. project_ids: type: array description: 'Optional `proj_` prefix IDs to scope the subscription to. Leave empty to receive events from all projects. ' items: type: string required: - url - event_type responses: '201': description: Webhook subscription created successfully content: application/json: schema: "$ref": "#/components/schemas/WebhookSubscription" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" "/v1/webhooks/subscriptions/{subscription_id}": patch: tags: - Webhooks summary: Update a webhook subscription description: Update one of your webhook subscriptions. operationId: updateWebhookSubscription parameters: - "$ref": "#/components/parameters/SubscriptionIdParam" requestBody: required: true content: application/json: schema: type: object properties: url: type: string description: The URL we'll send the POST request to. event_type: type: string enum: - new_todo description: The event to subscribe to. project_ids: type: array description: "`proj_` prefix IDs to scope the subscription to. Pass an empty array to receive events from all projects.\n" items: type: string responses: '200': description: Webhook subscription updated successfully content: application/json: schema: "$ref": "#/components/schemas/WebhookSubscription" '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Webhook subscription not found '422': description: Invalid input content: application/json: schema: "$ref": "#/components/schemas/Error" delete: tags: - Webhooks summary: Delete a webhook subscription description: Delete one of your webhook subscriptions. operationId: deleteWebhookSubscription parameters: - "$ref": "#/components/parameters/SubscriptionIdParam" responses: '204': description: Webhook subscription deleted successfully '403': description: Forbidden — read-only API key content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Webhook subscription not found "/v1/users/me": get: tags: - Viewer - Users summary: Return the authenticated user's details operationId: getAuthenticatedUser responses: '200': description: The authenticated user's details content: application/json: schema: "$ref": "#/components/schemas/User" '404': description: Not found "/v1/users/me/todos": get: tags: - Viewer - Todos summary: Return all (completed) todos for the authenticated user operationId: getAuthenticatedUserTodos parameters: - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" - "$ref": "#/components/parameters/SinceParam" - "$ref": "#/components/parameters/UntilParam" - "$ref": "#/components/parameters/QueryParam" - "$ref": "#/components/parameters/ExpandReactionsParam" responses: '200': description: A list of (completed) todos for the authenticated user content: application/json: schema: "$ref": "#/components/schemas/PaginatedTodos" '400': description: Invalid date format for since or until parameter content: application/json: schema: "$ref": "#/components/schemas/Error" '404': description: Not found "/v1/users/me/projects": get: tags: - Viewer - Projects summary: Return all projects for the authenticated user operationId: getAuthenticatedUserProjects parameters: - "$ref": "#/components/parameters/LimitParam" - "$ref": "#/components/parameters/StartingAfterParam" responses: '200': description: A list of projects for the authenticated user content: application/json: schema: "$ref": "#/components/schemas/PaginatedProjects" '404': description: Not found components: securitySchemes: ApiKeyHeader: type: http scheme: bearer description: 'Pass your API key as a Bearer token in the Authorization header. API keys start with `wip_sk_`. Bearer tokens without that prefix are treated as OAuth 2.0 access tokens. If both a query `api_key` and an Authorization header are provided, the query parameter takes precedence. ' ApiKeyQuery: type: apiKey in: query name: api_key description: 'Pass your API key as a query parameter. Prefer the Authorization header where possible — query parameters can be captured in server logs and browser history. ' OAuth2: type: oauth2 description: 'OAuth 2.0 access token for third-party applications. Pass as `Authorization: Bearer `. Tokens from the OAuth flow do not use the `wip_sk_` API key prefix. ' flows: authorizationCode: authorizationUrl: https://wip.co/oauth/authorize tokenUrl: https://wip.co/oauth/token scopes: {} parameters: LimitParam: name: limit in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 25 description: Number of items to return (max 100). StartingAfterParam: name: starting_after in: query required: false schema: type: string description: 'Cursor for pagination. Pass the `after` value from a previous response to fetch the next page of items. ' QueryParam: name: query in: query required: false schema: type: string description: 'Full-text search on todo body. Supports prefix matching and negation (e.g. `feature -bug`). ' ExpandReactionsParam: name: expand in: query required: false style: form explode: true schema: type: array items: type: string enum: - reactions description: 'Related records to include inline. Pass `reactions` to add a `reactions` array to each todo — a bounded preview (up to 5) of the most recent reactions, newest first, each with its `reactor`. Use `reactions_count` for the full total. Accepts a comma-separated list (`?expand=reactions`) or the repeated form (`?expand[]=reactions`). ' SinceParam: name: since in: query required: false schema: type: string description: 'Filter todos created since this date. Supports Unix timestamp in seconds (1704067200) or milliseconds (1704067200000), YYYY (2024), YYYY-MM (2024-01), YYYY-MM-DD (2024-01-15), or ISO 8601 datetime (2024-01-15T12:00:00Z). ' UntilParam: name: until in: query required: false schema: type: string description: 'Filter todos created until this date. Supports Unix timestamp in seconds (1704067200) or milliseconds (1704067200000), YYYY (2024), YYYY-MM (2024-01), YYYY-MM-DD (2024-01-15), or ISO 8601 datetime (2024-01-15T12:00:00Z). ' TodoIdParam: name: todo_id in: path required: true schema: type: string description: Todo ID (`todo_` prefix ID or numeric database ID). UsernameParam: name: username in: path required: true schema: type: string description: User identifier (username, `user_` prefix ID, or `me` for the authenticated user). ProjectIdParam: name: project_id in: path required: true schema: type: string description: Project identifier (`proj_` prefix ID or slug). CommentIdParam: name: comment_id in: path required: true schema: type: string description: Comment ID (`comm_` prefix ID). ReactionIdParam: name: reaction_id in: path required: true schema: type: string description: Reaction ID (`reac_` prefix ID). SubscriptionIdParam: name: subscription_id in: path required: true schema: type: string description: Webhook subscription ID (`hook_` prefix ID). UserIdParam: name: user_id in: path required: true schema: type: string description: User identifier (username, `user_` prefix ID, or `me` for the authenticated user). schemas: Error: type: object required: - error properties: error: type: string Todo: type: object required: - id - created_at - updated_at - body - url - attachments - creator - creator_id - projects - reactions_count - comments_count - viewer properties: id: type: string created_at: type: string format: date-time updated_at: type: string format: date-time body: type: string url: type: string attachments: type: array items: "$ref": "#/components/schemas/Attachment" creator: "$ref": "#/components/schemas/User" creator_id: type: string deprecated: true description: 'Deprecated: Use creator.id instead' user_id: type: string deprecated: true description: 'Deprecated: Use creator.id instead' projects: type: array items: "$ref": "#/components/schemas/Project" reactions_count: type: integer description: Number of reactions on this todo reactions: type: array description: 'A bounded preview (up to 5) of the most recent reactions, newest first, each with its reactor. Only present when the request includes `expand=reactions`. Use `reactions_count` for the full total. ' items: "$ref": "#/components/schemas/Reaction" comments_count: type: integer description: Number of comments on this todo viewer: type: object description: Data specific to the authenticated user required: - reactions - comments properties: reactions: type: array description: The authenticated user's reactions on this todo (empty array if none) items: type: object properties: id: type: string comments: type: array description: The authenticated user's comments on this todo (empty array if none) items: type: object properties: id: type: string Attachment: type: object required: - id - created_at - updated_at - url - mime_type - filename properties: id: type: string created_at: type: string format: date-time updated_at: type: string format: date-time url: type: string mime_type: type: string filename: type: string width: type: - integer - 'null' description: Pixel width of the media, when known. Use together with height to reserve layout space before the media loads. height: type: - integer - 'null' description: Pixel height of the media, when known. aspect_ratio: type: - number - 'null' description: Width divided by height, when known. Project: type: object required: - id - slug - name - pitch - description - created_at - updated_at - hashtag - website_url - privacy - archived - url - logo - header - header_color - owner - makers - followers_count - following properties: id: type: string slug: type: - 'null' - string name: type: string pitch: type: - 'null' - string description: type: - 'null' - string created_at: type: string format: date-time updated_at: type: string format: date-time hashtag: type: - 'null' - string website_url: type: - 'null' - string privacy: type: string enum: - public - protected - private archived: type: boolean url: type: string logo: type: object properties: small: type: - 'null' - string medium: type: - 'null' - string large: type: - 'null' - string header: type: - 'null' - object description: Banner/header image at several sizes (3:1 aspect ratio, WebP). Null when the project has no header image, in which case clients can fall back to `header_color`. properties: small: type: string medium: type: string large: type: string header_color: type: string description: Solid background color for the header/banner. Always present; derived from the header image when available, otherwise a fallback color. owner: "$ref": "#/components/schemas/User" makers: type: array items: "$ref": "#/components/schemas/User" followers_count: type: integer description: Number of users following this project. following: type: boolean description: Whether the authenticated user follows this project. Always `false` for unauthenticated requests. User: type: object required: - id - username - streak - created_at - updated_at - privacy - protected - first_name - last_name - bio - location - website_url - todos_count - time_zone - url - avatar - header - header_color - best_streak - streaking - followers_count - following properties: id: type: string username: type: string streak: type: integer created_at: type: string format: date-time updated_at: type: string format: date-time privacy: type: string enum: - public - protected - private protected: type: boolean deprecated: true description: 'Deprecated: use `privacy` instead. Returns `true` whenever `privacy` is not `public` (i.e. the account is `protected` or `private`).' first_name: type: - 'null' - string last_name: type: - 'null' - string bio: type: - 'null' - string description: The user's profile bio/description. location: type: - 'null' - string description: The user's self-reported location. website_url: type: - 'null' - string description: The user's personal website URL (e.g. blog or portfolio). Null when the user has not set one. todos_count: type: integer time_zone: type: string url: type: string avatar: type: object properties: small: type: string medium: type: string large: type: string header: type: - 'null' - object description: Profile banner/header image at several sizes (3:1 aspect ratio, WebP). Null when the user has no header image, in which case clients can fall back to `header_color`. properties: small: type: string medium: type: string large: type: string header_color: type: string description: Solid background color for the profile header/banner. Always present; derived from the header image when available, otherwise a fallback color. best_streak: type: integer streaking: type: boolean followers_count: type: integer description: Number of users following this user. following: type: boolean description: Whether the authenticated user follows this user. Always `false` for unauthenticated requests. PaginatedTodos: type: object required: - data - has_more - total_count properties: data: type: array items: "$ref": "#/components/schemas/Todo" has_more: type: boolean total_count: type: integer after: type: - 'null' - string description: 'Cursor for the next page. Pass as `starting_after` to fetch more results. Null when there are no more items. ' PaginatedProjects: type: object required: - data - has_more - total_count properties: data: type: array items: "$ref": "#/components/schemas/Project" has_more: type: boolean total_count: type: integer after: type: - 'null' - string description: 'Cursor for the next page. Pass as `starting_after` to fetch more results. Null when there are no more items. ' Upload: type: object description: | Contains credentials and information needed to perform a direct file upload to the storage provider. properties: filename: type: string description: Original filename byte_size: type: integer description: Size of the file in bytes checksum: type: string description: MD5 checksum of the file content_type: type: string description: MIME type of the file url: type: string description: Pre-signed URL where the file should be uploaded to key: type: string description: Storage key/path for the file signed_id: type: string description: Token to reference this file when attaching it to other resources method: type: string description: HTTP method to use for the upload (always "PUT") headers: type: object additionalProperties: type: string description: Headers that must be included in the upload request Reaction: type: object required: - id - created_at - reactable_type - reactable_id - reactor properties: id: type: string created_at: type: string format: date-time reactable_type: type: string description: The type of resource this reaction is on (Todo, Comment) reactable_id: type: string description: The ID of the resource this reaction is on reactor: "$ref": "#/components/schemas/User" Report: type: object required: - id - created_at - reportable_type - reportable_id properties: id: type: string description: Report ID (`rep_` prefix ID). created_at: type: string format: date-time reportable_type: type: string description: The type of resource reported (Todo, Comment, User) reportable_id: type: string description: The ID of the resource reported WebhookSubscription: type: object required: - id - url - event_type - project_ids - created_at - updated_at properties: id: type: string description: Webhook subscription ID (`hook_` prefix ID). url: type: string description: The URL we send the POST request to. event_type: type: string enum: - new_todo description: The event this subscription listens for. project_ids: type: array description: "`proj_` prefix IDs the subscription is scoped to. Empty means all projects.\n" items: type: string created_at: type: string format: date-time updated_at: type: string format: date-time Comment: type: object required: - id - body - created_at - updated_at - url - reactions_count - viewer - creator properties: id: type: string body: type: string created_at: type: string format: date-time updated_at: type: string format: date-time url: type: string reactions_count: type: integer description: Number of reactions on this comment viewer: type: object description: Data specific to the authenticated user required: - reactions properties: reactions: type: array description: The authenticated user's reactions on this comment (empty array if none) items: type: object properties: id: type: string creator: "$ref": "#/components/schemas/User" PaginatedComments: type: object required: - data - has_more - total_count properties: data: type: array items: "$ref": "#/components/schemas/Comment" has_more: type: boolean total_count: type: integer after: type: - 'null' - string description: 'Cursor for the next page. Pass as `starting_after` to fetch more results. Null when there are no more items. '