Quire API API Reference

Introduction

Welcome to the reference for the Quire REST API!

The Quire REST API provides a broad set of operations and resources that:

  • Consistently do repetitive or tedious tasks.
  • Chain a process together for your team’s process and workflow.
    • Pull information from other locations such as email and Evernote into Quire.
    • Push information from Quire to other locations such as email and Zapier.

Want to share your thoughts on how Quire API works for you? Tell us how you feel about using our API and what we can do to make it better.

REST is a web-service protocol for rapid development by using HTTP and JSON technology.

API Changelog

You can find the Changelog of the API Reference on GitHub.

Authentication

For full setup instructions, see our Complete Setup Guide on the Quire blog.

OAuth v2.0

Quire uses OAuth v2.0 to authenticate your app and access the Quire REST API on a user’s behalf—without requiring the user’s password.

Authenticating via OAuth2 requires the following steps:

  1. Register Your Application on Quire
  2. Ask a Quire User to Grant Access to Your Application
  3. Retrieve an Access Token
  4. Make Authenticated Requests

Register Your Application on Quire

Quire API

1. Give your app a cool name

Your app deserves a cool name that lives up to its broad range of great features.

All of the app users will see this name in public, so think carefully!

2. Choose the Quire Organization that your app belongs to

You can choose an organization in Quire that your app belongs to.

If one day you decide to leave the organization, you will lose the authority to manage the app.

3. Redirect URL

When users grant your app authorization request, users will be directed to the configured URL that you’ve set.

4. Choose permission scopes

You can set permission on what your app can do with Quire. There are several options for you to choose from.

Scope Allows the app to
Manage profiles Edit project and organization settings.
Create tasks Add new tasks.
Manage tasks Edit, assign, and schedule tasks and sublists.
Delete tasks Delete tasks.
Manage tags Add, edit, and remove tags.
Manage statuses Add, edit, and remove statuses.
Manage notifications Send notifications to users.

Note: Every app can read the organizations and projects a user authorized. If none of the options is selected, the app can only read user’s data, and Quire shows it as Read Only.

The scopes are fixed when a user grants access. If you change them later, a user gets the new ones only after authorizing your app again. The same goes for the Webhook URL: following a project or task with app (see WebHook) works only if your app had a Webhook URL when the user granted access (403 otherwise).

5. Development Client ID and Client Secret

Quire Open API

The Client ID and Client secret will be automatically generated as you create an app.

The Client ID is a unique ID to identify your app.

You should keep your client secret safe, which means you should never share your client secret with anyone. If you choose to regenerate the client secret, the old one will immediately become invalid.

6. Update your App

If your app hasn't been published to Quire App Directory, it will remain as unpublished status. You can still use the configured shareable link in the Developer App Console Distribution to share the app with other users for testing or integration.

When you make changes to the app, you can use the shareable link to access the development copy as well. Working on your development copy will not affect your live App Directory app. When your updated app is ready to be published and replace the old version on Quire App Directory, your published app will have a different Client ID to the unpublished one.

There are two sets of Client ID and Client Secret.

  • Development set - should be used during developing and testing internally of the app.
  • Production set - should be used once your app is ready and published on Quire App Directory.

Fulfill Authorization Request

Ask a Quire User to Grant Access to Your Application

Once registering your application, you can ask your user to grant access to your application.

The authorization endpoint lets users grant your app access to the requested permissions.

The authorization endpoint should look like this:

https://quire.io/oauth?client_id=your-client-ID&redirect_uri=your-redirect-uri

Quire Grant Access

After your user clicks Allow, the access will be granted, and he will be redirected to the URL you specified in the redirect_uri parameter with an authorization code provided as a query parameter called code.

After your app is granted, you can have an authorization code to exchange access token for access Quire API. The redirect_uri is optional. If omitted, the Redirect URL configured for your app is used. If specified, it must start with the configured Redirect URL.

Parameter Value
client_id {your-client-ID}
redirect_uri Optional. The redirect URL after granted. If specified, it must start with the Redirect URL configured for your app (for a loopback URL, any port is accepted; see below). Otherwise, the configured URL will be used.
state Optional. A random string generated by your app to protect from XSRF.

Loopback redirect URIs (native / CLI apps)

When the registered redirect URI's host is a loopback address — 127.0.0.1, [::1], or localhost — Quire accepts any port at request time, per RFC 8252 §7.3. Scheme, host, and path must still match the registered URI exactly.

For example, if your app registers http://127.0.0.1/callback, all of these are valid redirect_uri values at the authorize step (and must be echoed verbatim when exchanging the code):

http://127.0.0.1/callback
http://127.0.0.1:8866/callback
http://127.0.0.1:55123/callback

This lets installed apps (CLIs, desktop tools) bind to any free ephemeral port on the loopback interface and still receive the OAuth callback, without requiring users to keep a fixed port free. The rule applies only to loopback hosts — non-loopback redirect URIs continue to require a prefix match.

Retrieve Access Token

To retrieve the access token, you have to post a request to https://quire.io/oauth/token with the following data:

Parameter Value
grant_type authorization_code
code {your-authorization-code}
client_id {your-client-ID}
client_secret {your-client-secret}
redirect_uri Required if you specified redirect_uri in the previous authorization step. The value must be identical to the one used there.
curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=Your_code_from_previous_step&client_id=Your_app_client_id&client_secret=Your_app_client_secret&redirect_uri=Your_redirect_uri" \
  https://quire.io/oauth/token

The authorization code expires in 10 minutes and can be used only once.

Then, the access token will be returned in the response's body.

{
  "access_token":"ACCESS_TOKEN",
  "token_type": "bearer",
  "expires_in":3600,
  "refresh_token":"REFRESH_TOKEN"
}

The access token expires in 1 hour (expires_in is in seconds), and each request made with it extends it. Once it expires, use the refresh token to get a new one. The refresh token should be kept carefully and permanently since you need it to access every Quire API.

If a request to https://quire.io/oauth/token fails, the response is 400 with an OAuth error, for example:

{
  "error": "invalid_grant",
  "error_description": "The 'code' provided was invalid."
}

Refresh Access Token

To get a new access token, post a request to https://quire.io/oauth/token with the following data:

Parameter Value
grant_type refresh_token
refresh_token {your-refresh-token}
client_id {your-client-ID}
client_secret {your-client-secret}
curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token&refresh_token=Your_refresh_token&client_id=Your_app_client_id&client_secret=Your_app_client_secret" \
  https://quire.io/oauth/token

The response has the same shape as above, with a new access_token. The refresh_token stays the same, so keep using it.

PKCE Support

Quire supports PKCE (RFC 7636) for public clients such as single-page apps and installed CLIs. To use it:

  1. Add code_challenge and code_challenge_method=S256 to the authorization request.
  2. Send code_verifier instead of client_secret when exchanging the authorization code for a token.

Note: Only S256 is supported. The redirect_uri rule above also applies — if you specified one at the authorization step, you must echo the same value when exchanging the code.

Access token lifetime

PKCE-issued access tokens are valid for 7 days (vs. 1 hour for confidential clients) and aren't extended by use. The response does not include a refresh_token — public clients have no client_secret with which to authenticate the refresh-token grant. When the access token expires, run the authorization flow again to obtain a new one.

This applies whenever code_challenge is sent, even by a confidential client. If your app needs a refresh token, don't use PKCE.

The expires_in field of the token response reflects the actual remaining lifetime, in seconds.

Use Access Token to Access Quire API

In each request, the access token must be put in the header. The header name is Authorization and the value is Bearer your_token.

After you exchange the access token, your app can make requests to Quire API on behalf of the authorized users.

curl -H 'Authorization: Bearer {access_token}' \
https://quire.io/api/user/id/me
{
  "email": "john@gmail.cc",
  "website": "https://coolwebsites.com",
  "id": "My_ID",
  "description": "This is *cool*!",
  "url": "https://quire.io/u/My_ID",
  "nameText": "My Name",
  "nameHtml": "My Name",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "iconColor": "37",
  "name": "My Name",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Token Expiration

A refresh token might stop working for one of these reasons:

  • The user has revoked your app's access.
  • The refresh token has not been used for 6 months.
  • The user's account has been deleted.
  • The user granted only some organizations and projects, and all of them have been deleted.
  • Your app has been deleted.

Also, requests are rejected with 401 if the user hasn't signed in to Quire for more than 400 days, unless one of the user's organizations is on the Professional plan or above.

Publish App

Quire Publish App

By default, your app will be set as Private. You can change the app distribution to Public so that other Quire users can install your app to their workspace as well.

If your app is made available on Quire App Directory and you want to delete the app, you should communicate with your users first before deprecating the app.

WebHook

When one event on Quire is triggered, the system will send a payload to the webhook's configured URL.

A webhook is used by Quire to call an app, while Quire API is used by an app to call Quire. To receive these events, you have to specify a valid URL for Webhooks when configuring your app.

For a complete guide, see our blog post.

Every payload carries token, the Webhook Token you set when configuring your app, and secret, your app's Client Secret. Check both before trusting a payload, and ignore it if either doesn't match.

System Events

A system event is used to notify your app about system or app's activities.

Token Expiration

When the token has been expired or revoked, an event will be sent to your app. You can clean up your storage if necessary.

{
  "type": "system",
  "token": "hook-token-defined-by-you",
  "secret": "your-client-secret",
  "data": {
    "type": "token-revocation",
    "token": "the-refresh-token"
  }
}

Host Revocation

When the user revokes the grant to a host (either a project or an organization), an event will be sent to your app. You can clean up your storage if necessary.

{
  "type": "system",
  "token": "hook-token-defined-by-you",
  "secret": "your-client-secret",
  "data": {
    "type": "host-revocation",
    "token": "the-refresh-token",
    "host": "host-oid",
    "otype": "Project"
  }
}
  • host is the OID of the project or organization, and otype is "Project" or "Organization".
  • host is "*", with no otype, when the user revokes a grant that covered all their organizations and projects but still has other grants for your app.

Notification Events

A notification is the information about an update (aka., an activity). Here is an example:

{
  "type": "notification",
  "token": "hook-token-defined-by-you",
  "secret": "your-client-secret",
  "projectSummary": {
    "oid": "project-oid-where-event-occurred",
    "id": "project-id"
  },
  "organizationSummary": {
    "oid": "organization-where-event-occurred",
    "id": "organization-id"
  },
  "data": {
    "type": 0,
    "when": 1569831612000,
    "what": {
      "oid": "YxjapXXRCOYxoaiCT4tT3OQm",
      "id": 101,
      "name": "Brand new start",
      "parent": {
        "oid": "parent-oid",
        "id": 100,
        "parent": {
          "oid": "grand-parent-oid",
          "id": 99
        }
      }
    },
    "user": {
      "oid": "1AbDEFed2A5031BEDDweqmde",
      "id": "john.doer",
      "name": "John Doer"
    },
    "message": "<a href=\"https://quire.io/u/john.doer\">John Doer</a> added <a href=\"https://quire.io/w/MyProjects/101\">Brand new start</a>",
    "text": "John Doer added Brand new start",
    "url": "https://quire.io/w/MyProjects/101"
  } 
}
  • type is the activity's type (see Activity Types), and when is when it happened, in milliseconds since the epoch.

  • what is the task, project, or organization the activity is about, depending on type. It is the full record, as Get an existing task by its ID, Get a project by ID or Get an organization by ID returns it, except that a task carries no formula field values.

  • user is the user who did it.

  • The data map may also include an optional value field, which provides detailed information as a map. For example, for an assignment notification, value includes the assignee’s ID, name, and URL.

  • For a reminder's change (types 84, 87, 88, 192, 193 and 194 in Activity Types), value is the reminder itself, as Get a reminder by OID returns it, or only its oid once removed.

  • If the notification is about a start or due change, the data map will include an additional due field. This value is a date/time formatted in the user’s locale and time zone.

  • If what is a task, its parent field holds the parent's oid and id, or null if the task has no parent. If the task’s parent also has a parent, the map includes a nested parent field as well.

  • The projectSummary and organizationSummary fields provide information about the project and organization where the event occurred.

  • There is an additional field, taskSummaries, for activities that can affect multiple tasks (for example, removing a task that has subtasks). This field is a list of map instances. Each map represents a task that was changed. If any of that task's subtasks were also changed, they are included in the map’s tasks field.

Registration for Notifications

For instructions on updating a project or a task, see Update a project by ID and Update an existing task by its ID.

If the app wants to receive notifications of specific projects or tasks, it can follow the projects or tasks by sending a PUT request to the URL. To add a follower, the body of the request can be:

Syntax 1

{
  "addFollowers": ["app"]
}

where app is a keyword. It indicates that the app would like to receive the notifications about the given target (a project or a task). That is, it'll add the app into the target's followers.

Syntax 2

In addition, you can specify additional information that will be passed as part of a notification in the following syntax.

"app|team|channel"

where app is a keyword while team and channel are application specific. That is, you can pass any value to team and channel.

Note: team and channel can not contain '|'.

For example,

{
  "addFollowers": ["app|extra101"]
}

Then, the notification will carry an additional field called team with the value "extra101" (data is the same as without it; it's left empty in these examples):

{
  "type": "notification",
  "team": "extra101",
  "data": {}
}

Another example:

{
  "addFollowers": ["app|extra101|channel9"]
}

You'll get:

{
  "type": "notification",
  "team": "extra101",
  "channel": "channel9",
  "data": {}
}

Syntax 3

"app|team|channel|mine"

where both app and mine are keywords. It is similar to Syntax 2, except it receives only notifications that match the notification setting of the user.

If you don't need both team and channel, you can specify: "app|||mine".

The notification setting can be found at https://quire.io/w/YourProject?view=setting&tab=options#notifications

Syntax 4

"app|/path"

where app is a keyword, and /path is application specific. The path will be appended to the app's hook URL. For example, assume the app's hook URL is "https://super.app/hooks/standard", and the follower "app|/soc/id279/channel51". Then, the notification will be posted the following URL: "https://super.app/hooks/standard/soc/id279/channel51".

Syntax 5

If you'd like to pass additional information in this syntax, you can append it as follows.

"app|/path|channel"

For example, app|/soc/id8|box51. Then, box51 will be part of the JSON object sent to the hook URL.

{
  "type": "notification",
  "channel": "box51",
  "data": {}
}

Responding and Retries

When receiving the notification, your Web Hook shall return a status code between 200 and 299 within 1 minute to indicate success.

If a status code other than above is returned, or there is no response within 1 minute, we will retry 2 hours later, then 1 day later. If the last retry fails too, the payload is dropped.

Payloads to the same URL are posted one at a time. After 5 failures in a row, the URL is treated as down: new payloads to it wait for the retries above instead of being posted right away, and the admins of your app's organization get an email (at most once a day). Quire keeps probing the URL and resumes delivery once it returns a 2xx status again.

Activity Types

Rate Limits

To protect the stability of the API and keep it available to all users, Quire enforces multiple kinds of rate limiting. Requests that hit any of our rate limits will receive a 429 Too Many Requests response. We may change these quotas or add new quotas in the future.

Here are the limits by plan.

Plan Maximum requests per organization, per minute Maximum requests per organization, per hour
Free 50 200
Professional 300 1,250
Premium 1,000 5,000
Enterprise 100 × members, at least 1,000 500 × members, at least 5,000

Note: the limit is per-organization. It sums up the total number of all accesses from all applications for each organization. Organizations that share one subscription also share one limit: their accesses are summed up together. Enterprise quotas scale with the number of paid members in the organization. A trial doesn't change these limits; they stay those of the plan before the trial. For more quota, please refer to Pricing.

Note: a personal project (the one behind My Tasks) is metered against its own bucket at half the limits of the best plan among the user's organizations, trials excluded — e.g. 25 per minute / 100 per hour on the Free plan. For Enterprise, it is half the Premium limits: 500 per minute / 2,500 per hour.

When a rate limit is exceeded, the response includes a standard Retry-After header whose value is the number of seconds to wait before retrying. The value reflects the time until the offending per-minute or per-hour counter resets, so clients can back off precisely instead of guessing.

HTTP/1.1 429 Too Many Requests
            Retry-After: 37
            Content-Type: application/json
            
            {"code": 429, "message": "..."}
            

Apart from the limits above, more than 500 requests in progress at once with the same access token from the same IP address also receive 429, with Retry-After: 30. Wait for pending requests to complete before sending more.

To inspect current usage without consuming budget, call GET /rate-limit/id/{id} (or /rate-limit/{oid}). Calls to that endpoint are free — they never count against the quota.

Request cost

Most calls cost 1 unit against the per-minute / per-hour budget above — a single-item GET / POST / PUT / DELETE on one record, a storage call, and so on. A few endpoint families scale their cost with how much work they actually do:

Endpoint family Cost
Task list, subtree, and search (GET) max(1, ceil(items / 100)) units, where items is the number of tasks returned. So ?limit=100 (or fewer) costs 1, ?limit=1000 costs 10, ?limit=no returning 5,000 items costs 50.
Bulk write — bulk-add, bulk-update, bulk-remove, bulk-move, bulk-transfer, bulk-approve N units, where N is items.length in the request body (for bulk-add, every task created, nested tasks included) — the same total cost as N equivalent single-task calls. ?dry-run=true halves it to ceil(N / 2) (minimum 1). A batch holds at most 300 items, and no more than the per-minute limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan; over the plan's limit is rejected with 402 (code 469), over 300 with 400.
POST /task with nested tasks 1 unit per task created, nested ones included. Capped like a bulk write: at most 300 tasks, and no more than the per-minute limit.
Project CSV / JSON export 5 + max(1, ceil(tasks / 100)) units — the same per-100 read cost as a list, plus a flat 5-unit export surcharge. tasks counts only those matching the ?status= filter, not the project total. So a 100-task export costs 6, a 1,000-task export costs 15, and a 5,000-task export costs 55. Only an export that runs costs this: one rejected with 402 for the plan costs 1 unit, like any call.
POST /notification ceil(recipients / 10) units (minimum 1), counted from the resolved recipient list. Charged only after the recipients are resolved, so a call rejected with 404 costs nothing.
GET /insight/run/{oid} 1 unit, plus ceil(tasksLoaded / 250) - 1 when more than 250 tasks are loaded. tasksLoaded reflects the ?status=-filtered task set, so a tighter filter lowers the charge.
GET /rate-limit/..., GET /user/{oid}, GET /user/id/{id}, GET /user/list, GET /project/list (without an organization), GET /organization/list Free — never counted.

Size limits

The body of a request can't be larger than 1 MB; a larger one gets 413 Content too large. Two exceptions:

  • A storage value is at most 4 KiB as JSON; a larger one gets 413.
  • A file uploaded with attach is limited by the plan's per-file size and storage quota instead; over either, 402 (code 469).

Compact Responses

Many endpoints accept an optional ?return= query parameter to control the shape of the response body:

  • full (default) — the full record.
  • compact — identifiers only:
Entity Compact shape
Task, project, organization, sublist, document, chat, insight, dashboard {"oid": "…", "id": …}
Comment, reminder, tag {"oid": "…"}
Custom field (of a project or an insight) {"name": "…"}
Approval category {"id": "…"}
Status {"value": …}

💡 Tip — pass ?return=compact whenever you don't need the full record back. It is strictly better for the caller (less bandwidth, fewer LLM tokens) and for the server, which then skips a post-write reload plus the full response render — including per-user lookups, custom-field expansion, and so on. The default stays full only for backward compatibility; new callers (MCP integrations, scripted clients, anything that just chains calls by OID/ID) should default to compact.

Where it applies

?return= is honored by:

  • Single-item POST / PUT create and update endpoints, and every PUT …/undo-remove/… (task, comment, sublist, document, chat, insight, dashboard).
  • GET /task/list/…, in both the flat and the ?depth>1 subtree form. Items render as {oid, id, cursor?}, and subtree nodes as {oid, id, tasks?, cropped?}.
  • Bulk write endpoints, where it applies to every element of the returned array; null slots for skipped items are preserved in either mode. See Rate Limits for what those calls cost.

It is ignored by a GET on a single record, by DELETE, by the search endpoints (search, search-organization, search-folder), and by the timelog, attach, emoji, storage, and notification endpoints — their response shape is fixed. DELETE /task/bulk-remove/… likewise ignores it, since its response is already in identifier shape.

On an endpoint that honors ?return=, an empty value means full, and any value other than full or compact returns 400 Bad Request. Elsewhere any value is ignored.

Status Codes

Code Meaning Description
200 Success Request successful
204 No Content Request successful; the endpoint has no response body to return. A DELETE also returns 204 if the resource doesn't exist, except remove-timelog, which returns 404 when no time log matches, and any /storage/id/… path (404: storage has no ID form).
400 Bad Request You're using a wrong parameter, or passing incorrect data.
401 Unauthorized Invalid or expired token.
402 Payment required The organization’s subscription does not permit use of this app, the subscription has expired, or a plan quota/limit has been reached (body code 469 or 470 — see below).
403 Forbidden Not authorized to access the resource, the Authorization header is missing or malformed (body code 100), or temporarily blocked (body code 471 — see below).
404 Not Found The specified resource could not be found.
405 Method not allowed Method not allowed or supported.
408 Request Timeout The request took longer than 10 minutes to process. Retry later, or split it into smaller requests.
409 Conflict The request conflicts with the current state, such as creating something that already exists. message says what conflicts.
413 Content too large The request's content is larger than 1 MB, or a storage value is larger than 4 KiB. A file upload is limited by the plan instead (402).
418 Not valid JSON content The request's content doesn't appear to be JSON.
429 Too Many Requests Exceeded the rate limit for API calls, or sent too many requests at once. Carries a Retry-After header.
500 Internal Server Error There is an unexpected error.
503 Service Unavailable Server is down for maintenance.

Error Responses

All 4xx and 5xx responses share a common JSON envelope, represented by the ErrorResponse schema:

{ "code": 400, "message": "Invalid value for `priority`: foo (expected -1, 0, 1, or 2)." }
  • code is the HTTP status code, echoed in the body — except for 402, where it is 469 (a plan quota/limit has been reached) or 470 (the subscription has expired), and for 403, where it is 471 if the account is temporarily blocked, or 100 if the Authorization header is missing or malformed. These let clients tell the cases apart without parsing message.
  • message is a human-readable description, typically naming the offending field and — for 400 — the expected format. Long submitted values are truncated.

Each endpoint's Responses block lists the specific status codes that endpoint can emit; the body shape is this same envelope everywhere.

Error Code Meaning
100 General authentication error, such as a missing or malformed Authorization header (returned with HTTP 403).
400 Bad request including wrong request body, wrong parameter and so on.
401 Invalid or expired token.
403 Forbidden.
404 Resource not found.
405 Method not allowed.
408 Request timeout.
409 Conflict.
413 Request too large.
429 Too many invocations (the rate limit).
469 Quota exceeded, such as number of projects, number of members, and other plan limits. Returned with HTTP 402.
470 Subscription expired. Returned with HTTP 402.
471 Temporarily blocked; try again later. Returned with HTTP 403.
500 General invocation error. Most likely, an internal error.

Quire MCP Server

Quire offers an MCP (Model Context Protocol) server that lets AI assistants — Claude, ChatGPT, Cursor, VS Code, and other MCP-compatible clients — work with your Quire workspace through natural language.

Once connected, the assistant can list and search your projects, create or update tasks and subtasks, post comments, manage tags, sublists, statuses, documents, chats, insights, dashboards, and more — all on your behalf and within the permissions you grant.

Quire MCP is built on top of the same Quire REST API documented here, so anything an integration can do via REST is reachable from an AI assistant once it is connected.

Server URL

The Quire MCP server is hosted at:

https://mcp.quire.app/mcp

Authentication is handled by OAuth 2.1 — your AI assistant walks you through the standard authorization screen, you approve access for the workspaces you choose, and the assistant receives a token scoped to your account. No client ID or client secret needs to be configured by the end user.

The server speaks the Streamable HTTP transport and supports Dynamic Client Registration (RFC 7591) and PKCE (RFC 7636), so any compliant MCP client can connect with just the URL above.

What you can do

The Quire MCP server exposes the full Quire object model as MCP tools. At a high level:

Category What the AI can do
User & Organizations Identify the current user, look up users, list and update organizations
Projects List, search, and inspect projects; manage members, custom fields, and approval categories
Tasks Create, update, move, transfer, complete, approve, and delete tasks; manage dates, peekaboo, and time logs; search across a project, folder, or organization
Bulk operations Create, update, move, transfer, approve, or delete many tasks in one call
Subtasks & Sublists Build task hierarchies, group tasks into sublists, and reorder within sublists
Comments & Attachments Read and post comments on tasks and chats; attach files to tasks or comments
Tags & Statuses Manage the project's tag library and workflow statuses
Documents Create, read, update, and delete project documents
Chats & Insights Start chat threads, post chat comments, and manage insight reports and their fields
Dashboards Create, read, update, archive, and delete dashboards for a project, organization, or folder (widget contents are not yet exposed)
External teams List and inspect a project's external teams (partners)
URL resolver Turn any pasted Quire URL (task, project, document, …) into the underlying object

For the authoritative, always-up-to-date list of tools and their parameters, run tools/list from your MCP client after connecting.

Connect your AI assistant

You only need the server URL — the authorization flow is started by the client and completed in your browser.

Claude Desktop

  1. Open Settings → Connectors.
  2. Click Add custom connector.
  3. Enter a name (for example, Quire) and the URL https://mcp.quire.app/mcp.
  4. Save and click Connect. Claude Desktop will open a browser window where you can sign in to Quire and grant access.

Claude Code

Add the server with one command:

claude mcp add --transport http quire https://mcp.quire.app/mcp

Then trigger the OAuth flow from inside Claude Code:

/mcp

Pick quire, follow the link to authorize, and you're done.

Gemini CLI

Edit ~/.gemini/settings.json (user scope) or .gemini/settings.json (project scope):

{
  "mcpServers": {
    "quire": {
      "httpUrl": "https://mcp.quire.app/mcp",
      "authProviderType": "dynamic_discovery"
    }
  }
}

Restart Gemini CLI, then trigger OAuth:

/mcp auth quire

dynamic_discovery makes the CLI auto-detect the OAuth requirement, register a client, and open a browser to authorize. (OAuth requires that your local machine can receive a redirect on http://localhost:7777/oauth/callback.)

Codex CLI

Add the server with one command:

codex mcp add quire --url https://mcp.quire.app/mcp

Or edit ~/.codex/config.toml directly:

[mcp_servers.quire]
url = "https://mcp.quire.app/mcp"

Then trigger the OAuth flow:

codex mcp login quire

Codex CLI opens a browser where you sign in to Quire and approve access. (If your environment needs a fixed callback port, set mcp_oauth_callback_port at the top of config.toml.)

ChatGPT

ChatGPT supports remote MCP servers as Plugins (available on Plus, Pro, Business, Enterprise, and Edu plans).

  1. Open chatgpt.com and go to Settings → Plugins.
  2. Click Browser plugins.
  3. Click the + icon at the upper right corner to add a new plugin.
  4. Enter a name (for example, Quire) and the URL https://mcp.quire.app/mcp.
  5. Sign in to Quire when prompted and approve access.

Perplexity

Perplexity supports remote MCP servers as Custom Connectors on paid plans (Pro, Max, Enterprise).

  1. Open perplexity.ai and go to Settings → Connectors.
  2. Click Add Connector → Advanced (or Add custom connector).
  3. Enter a name (for example, Quire), set the URL to https://mcp.quire.app/mcp, and choose Streamable HTTP as the transport with OAuth as the authentication method.
  4. Save, then click Connect and sign in to Quire to approve access.

Microsoft Copilot Studio

Copilot Studio connects to remote MCP servers through the MCP onboarding wizard in your agent.

  1. Open your agent in Copilot Studio and go to the Tools page.
  2. Select Add a tool → New tool → Model Context Protocol.
  3. Fill in the wizard:
    • Server name: Quire
    • Server description: a short summary the agent orchestrator can use to decide when to call the server (for example, "Manage Quire projects, tasks, and comments").
    • Server URL: https://mcp.quire.app/mcp
    • Authentication: OAuth 2.0 → Dynamic discovery.
  4. Select Create, then Next. On Add tool, choose Create a new connection, sign in to Quire, and approve access.
  5. Click Add to agent.

Dynamic discovery uses Quire's OAuth metadata to register a client and complete authorization automatically — no client ID or secret needs to be configured by hand.

Cursor

Add the following entry to your MCP settings (~/.cursor/mcp.json or Settings → MCP):

{
  "mcpServers": {
    "quire": {
      "url": "https://mcp.quire.app/mcp"
    }
  }
}

Reload Cursor and complete the OAuth flow when prompted.

VS Code (GitHub Copilot Chat)

Create or edit .vscode/mcp.json in your workspace (or the user-level equivalent):

{
  "servers": {
    "quire": {
      "type": "http",
      "url": "https://mcp.quire.app/mcp"
    }
  }
}

Open the Command Palette and run MCP: List Servers, select quire, and start it. VS Code will open a browser to authorize.

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "quire": {
      "serverUrl": "https://mcp.quire.app/mcp"
    }
  }
}

Restart Windsurf and authorize when prompted.

Other MCP clients

Any client that supports Streamable HTTP MCP servers with OAuth can connect — just point it at https://mcp.quire.app/mcp. For clients that only speak the older stdio transport, use a bridge such as mcp-remote:

{
  "mcpServers": {
    "quire": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.quire.app/mcp"]
    }
  }
}

Authorization scopes

The first time you connect, Quire shows the standard authorization screen. You can choose:

  • Which organizations and projects the assistant may access.
  • What it may do — the same permission scopes that apply to regular Quire OAuth apps (see Authentication).

You can revoke access at any time from your Quire account settings, or by removing the connector from your AI client.

Privacy and rate limits

  • Quire MCP requests count against the same per-organization API quotas as direct REST calls — see Rate Limits.
  • Conversations with your AI assistant are not stored on Quire's servers; the MCP server only sees the individual tool calls the assistant makes on your behalf.
  • All traffic is encrypted in transit (HTTPS); access tokens are never exposed to model output.

Troubleshooting

  • "Connection refused" or "Failed to authenticate" — make sure the URL is exactly https://mcp.quire.app/mcp (with the /mcp path) and that your client supports the Streamable HTTP transport.
  • Authorization screen never appears — some clients require you to manually trigger the OAuth flow (for example, /mcp in Claude Code). Check the client's MCP server panel for an "authorize" button or status message.
  • The assistant can't see a project — confirm the project belongs to an organization you authorized, and that your Quire role on that project allows the action you're asking for.
  • Tool calls return 429 Too Many Requests — you have hit the per-organization rate limit. The assistant will receive a Retry-After value; wait that many seconds before retrying.

If a problem persists, contact Quire support with the timestamp of the failing request and (if shown) the request ID surfaced by the MCP client.

Quire CLI

Quire offers a command-line interface (@quire-io/quire-cli) that lets developers and power users drive their Quire workspace from a terminal or a shell script.

Once you are signed in, you can list and search projects, create or update tasks and subtasks, post comments, manage tags, sublists, statuses, documents, chats, insights, and more — and pipe the results into jq, xargs, or any other Unix tool.

Quire CLI is built on top of the same Quire REST API documented here, so anything an integration can do via REST is reachable from your terminal once you have signed in.

Install

The CLI ships through three channels.

Requires Node 20 or later.

npm install -g @quire-io/quire-cli
quire --version

Try it without installing:

npx @quire-io/quire-cli --help

The package is published as @quire-io/quire-cli; the installed binary is named quire.

Homebrew

For macOS or Linux users with Homebrew:

brew install quire-io/quire/quire
quire --version

This installs the same single-file binary that GitHub Releases ships, via the quire-io/homebrew-quire tap. After the first install, brew upgrade quire keeps you on the latest version.

Single-file binary

For machines that do not have Node, download a pre-built binary from the GitHub Releases page. One artifact per platform is attached to every release:

Platform Filename
macOS, Apple Silicon quire-darwin-arm64
macOS, Intel quire-darwin-x64
Linux, x86_64 quire-linux-x64
Linux, ARM64 quire-linux-arm64
Windows, x86_64 quire-win-x64.exe

Each release also ships a SHA256SUMS file so you can verify the download. On Unix:

curl -LO https://github.com/quire-io/quire-cli/releases/latest/download/quire-darwin-arm64
curl -LO https://github.com/quire-io/quire-cli/releases/latest/download/SHA256SUMS
shasum -a 256 -c SHA256SUMS --ignore-missing
chmod +x quire-darwin-arm64
mv quire-darwin-arm64 /usr/local/bin/quire
quire --version

The binaries embed Node 22 LTS, so no separate runtime is required.

Updating

How you update the CLI depends on how you installed it:

Installed via Upgrade command
npm i -g npm i -g @quire-io/quire-cli@latest
Homebrew brew upgrade quire
npx nothing — npx @quire-io/quire-cli always pulls the latest unless you pinned a version
GitHub Releases binary re-download from the Releases page and replace the binary on $PATH

Check your installed version with quire --version and compare against the Releases page.

Get started

quire login          # opens your browser, runs OAuth, saves credentials locally
quire whoami         # confirms the signed-in user and lists their organizations
quire project list   # first read against the API

quire login runs the OAuth public-client flow ( PKCE, RFC 7636) over a loopback redirect ( RFC 8252). The browser opens to the Quire authorization screen; after you approve, control returns to the CLI and the resulting tokens are saved to:

  • ~/.config/quire/credentials.json on Linux and macOS (mode 0600)
  • %APPDATA%\quire\credentials.json on Windows

The file is encrypted at rest with AES-256-GCM. The key is derived from your username and hostname, so a copy of the file taken to another machine or another user account cannot be decrypted.

As a public client, the CLI gets no refresh token: the access token lasts 7 days, after which you run quire login again.

What you can do

The CLI exposes the full Quire object model as subcommands. Run quire --help for the top-level list, or quire <command> --help for any subcommand.

Category Commands
User & Organizations quire whoami, quire user get, quire org list / get / update / limit
Projects quire project list / get / update / members / export, quire project field, quire project approval-category
Tasks quire task list / get / tree / search / subtasks / comments, quire task create / subtask / update / complete / uncomplete / move / transfer / delete, quire task dates / peekaboo / approve / revoke-approval, quire task timelog, quire mine
Bulk operations quire task bulk-create / bulk-update / bulk-delete / bulk-move / bulk-transfer / bulk-approve / bulk-subtasks (up to 300 tasks per call; fewer on the Free plan or in a personal project, see Rate Limits)
Sublists quire sublist list / get / create / update / delete / add-task / remove-task / undo-remove
Tags & Statuses quire tag and quire status (list / get / create / update / delete)
Comments & Attachments quire comment list / get / add / update / delete, quire task attach, quire comment attach
Chats quire chat list / get / create / update / delete / comments, quire chat comment add
Documents quire doc list / get / create / update / delete / undo-remove
Insights quire insight list / get / create / update / delete, quire insight field
Partners quire partner list / get
Notifications quire notify — send a self-targeted in-app notification
URL resolver quire resolve — turn any Quire URL into the underlying object
Undo quire undo — restore a recently deleted task, sublist, document, comment, chat, or insight
Reference quire colors — list Quire's 48-slot color palette

Output modes

Every command supports three output modes, controlled by global flags:

  • Default — colorized, human-readable tables (or aligned key-value blocks for get commands). Long cells are truncated; pass --no-truncate to keep the full text.
  • --json — the raw API response, unmodified, on stdout. Designed to round-trip through jq, yq, or any other JSON tool.
  • --quiet (-q) — only the resource ID, one per line. Designed for xargs.

Examples:

# human-readable
            quire task search "release notes" --project my-project --mine
            
            # scriptable
            quire task search "release notes" --project my-project --json | jq '.[].name'
            
            # pipeline-friendly
            quire task search "stale" --project my-project -q | xargs -L1 quire task complete
            

Other useful global flags:

  • --color-mode auto|always|never (or NO_COLOR=1) controls ANSI colors.
  • --yes auto-confirms destructive prompts (quire task delete, quire task bulk-delete, …). Required for non-interactive use.
  • --profile <name> selects a credentials profile (see below).
  • --verbose prints debug information to stderr.

The CLI keeps stdout clean for piping: prompts, progress messages, and warnings all go to stderr, and a broken pipe (e.g. quire ... | head) exits 0 silently.

Profiles

The CLI supports multiple credentials stores via --profile. Each profile gets its own file (credentials.<name>.json) under the same config directory.

quire login   --profile work
quire login   --profile personal
quire whoami  --profile work
quire mine    --profile personal

The default profile is default; override per shell with QUIRE_PROFILE=....

quire logout [--profile <name>] deletes the local credentials file. It does not revoke the CLI's access on the Quire server. To do that, also open Account Settings > Apps ( https://quire.io/r/setting?tab=app) and remove the Quire CLI app.

Configuration

Environment variable Default Purpose
QUIRE_PROFILE default Profile selected when --profile is not passed
QUIRE_CONFIG_HOME ~/.config/quire/ (Unix), %APPDATA%\quire\ (Windows) Where credentials and other CLI state live
QUIRE_API_SERVER https://quire.io/api Override the API base URL (advanced; the CLI prints a warning to stderr when set)
QUIRE_CLI_LOOPBACK_PORT 8866 Local port the OAuth callback listens on. Any free port works, since Quire accepts any port on a loopback redirect URI
NO_COLOR unset Set to any value to disable ANSI colors

Authorization scopes

The first time you run quire login, Quire shows the standard authorization screen. You can choose:

  • Which organizations and projects the CLI may access.
  • What it may do — the same permission scopes that apply to regular Quire OAuth apps (see Authentication).

You can revoke access at any time by removing the Quire CLI app in Account Settings > Apps ( https://quire.io/r/setting?tab=app).

Privacy and rate limits

  • CLI requests count against the same per-organization API quotas as direct REST calls — see Rate Limits. On a 429, the CLI waits for the Retry-After value (with a small jitter, capped at 60 seconds) and retries once before failing.
  • Credentials live only on the machine where you ran quire login. Nothing is sent to Quire other than authenticated API calls.
  • All traffic is encrypted in transit (HTTPS); access tokens never appear in command output, only in the encrypted credentials file.

Troubleshooting

  • Not logged in. Run \quire login`.` — credentials are missing, expired, or revoked. Run quire login again.
  • The browser does not open during quire login. — the authorization URL is also printed to stderr. Copy and paste it into any browser; the loopback callback will still complete the flow.
  • Failed to bind 127.0.0.1:8866 — another process is using the OAuth callback port. Pick a free port, set QUIRE_CLI_LOOPBACK_PORT=<port>, and re-run quire login.
  • 429 Too Many Requests — the CLI auto-retries once after the server-supplied delay. Past that, wait and re-run; the per-organization rate limit is documented at Rate Limits.
  • quire ... | head prints a broken-pipe stack trace. — you should not see this; the CLI catches EPIPE and exits 0. If you do see it, please report it as a bug.
  • Output looks corrupted on Windows. — make sure your terminal supports ANSI escape sequences (Windows Terminal, VS Code's terminal, and modern PowerShell do). Otherwise pass --color-mode never or set NO_COLOR=1.

If a problem persists, contact Quire support with the timestamp of the failing request, the command line you ran (with any tokens or IDs redacted), and — if helpful — the output of the same command with --verbose.

Emojis

When adding or removing a comment's emoji reactions, an emoji can be given as the emoji itself or by one of its names below, with or without colons and in any case. The names are the shortcodes GitHub and Slack use. For example, +1, :thumbsup: and 👍 are the same.

Emoji Names
😃 smiley
😞 disappointed
😐 neutral_face
😂 joy
😍 heart_eyes
😜 stuck_out_tongue_winking_eye
😏 smirk
😱 scream
😭 sob
😡 rage, pout
👍 +1, thumbsup
👎 -1, thumbsdown
🙌 raised_hands
👊 punch, facepunch, fist_oncoming
💪 muscle
❤️ heart
🎉 tada
🚀 rocket
💯 100
⚠️ warning

❤ and ⚠ without the variation selector (U+FE0F) are accepted as ❤️ and ⚠️. Responses always return the emoji itself.

💡 Tip — prefer names when calling from a script or an AI assistant. A name needs no percent-encoding in the URL, and it can't fall victim to a missing variation selector or a look-alike character. POST /comment/add-emoji/{commentOid}/+1,tada is the same request as POST /comment/add-emoji/{commentOid}/%F0%9F%91%8D,%F0%9F%8E%89.

API Endpoint
https://quire.io/api
Schemes: https
Version: 1.0.0

chat

Chat channels.

Create a chat channel by owner OID.

POST /chat/{ownerType}/{ownerOid}

Adds a new chat channel to the specified owner (currently only project) and returns it.

Example — POST /chat/id/project/my_project:

{
  "name": "Design",
  "followers": ["me"]
}

Returns 402 if the plan's chat-channel limit is reached.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /abc123 is equivalent to /project/abc123.

ownerOid: string
in path

Owner OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

followers: string[]

(Optional) Users (OID, ID, or email) who follow this chat channel. Only those listed follow it, so include "me" for the current user to follow.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created chat channel.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project, or none from an external team member sharing with every member; or the owner is not a project.

402 Payment Required

Payment Required — chat-channel quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a chat in this owner.

404 Not Found

Not Found — parent owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create a chat channel by owner ID.

POST /chat/id/{ownerType}/{ownerId}

Adds a new chat channel to the specified owner (currently only project) and returns it.

Example — POST /chat/id/project/my_project:

{
  "name": "Design",
  "followers": ["me"]
}

Returns 402 if the plan's chat-channel limit is reached.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /id/foo is equivalent to /id/project/foo.

ownerId: string
in path

Owner ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

followers: string[]

(Optional) Users (OID, ID, or email) who follow this chat channel. Only those listed follow it, so include "me" for the current user to follow.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created chat channel.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project, or none from an external team member sharing with every member; or the owner is not a project.

402 Payment Required

Payment Required — chat-channel quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a chat in this owner.

404 Not Found

Not Found — parent owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a chat channel by ID.

GET /chat/id/{ownerType}/{ownerId}/{chatId}

Returns the full chat channel record for the given owner and channel ID.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

chatId: string
in path

Chat channel ID.

200 OK

OK — chat channel record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a chat channel by OID.

GET /chat/{oid}

Returns the full chat channel record.

oid: string
in path

Chat channel OID.

200 OK

OK — chat channel record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List chat channels by owner ID.

GET /chat/list/id/{ownerType}/{ownerId}

Returns the project's chat channels that the caller can see; one shown to selected members only is left out for the others. Archived channels are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /list/id/foo is equivalent to /list/id/project/foo.

ownerId: string
in path

Owner ID.

200 OK

OK — list of chat channels (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — parent owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?chat=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "mutes": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "members": [
      "#/definitions/SimpleIdentity"
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List chat channels by owner OID.

GET /chat/list/{ownerType}/{ownerOid}

Returns the project's chat channels that the caller can see; one shown to selected members only is left out for the others. Archived channels are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /list/abc123 is equivalent to /list/project/abc123.

ownerOid: string
in path

Owner OID.

200 OK

OK — list of chat channels (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — parent owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?chat=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "mutes": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "members": [
      "#/definitions/SimpleIdentity"
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Undo the removal of a chat channel by ID.

PUT /chat/undo-remove/id/{ownerType}/{ownerId}/{chatId}

Restores a previously-removed chat channel. Idempotent: if the channel is not currently removed, this is a no-op and returns the current channel record.

Subject to the chat-channel-per-project quota: may return 402 Payment Required if the plan's chat-channel limit is already reached.

ownerType: string
in path

Owner type. Currently only project is supported. If omitted, project is assumed; e.g., /undo-remove/id/foo/bar is equivalent to /undo-remove/id/project/foo/bar.

ownerId: string
in path

Owner ID.

chatId: string
in path

Chat channel ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored chat channel.

402 Payment Required

Payment Required — chat-channel quota reached.

403 Forbidden

Forbidden — caller lacks permission to modify this chat.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of a chat channel by OID.

PUT /chat/undo-remove/{oid}

Restores a previously-removed chat channel. Idempotent: if the channel is not currently removed, this is a no-op and returns the current channel record.

Subject to the chat-channel-per-project quota: may return 402 Payment Required if the plan's chat-channel limit is already reached.

oid: string
in path

Chat channel OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored chat channel.

402 Payment Required

Payment Required — chat-channel quota reached.

403 Forbidden

Forbidden — caller lacks permission to modify this chat.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a chat channel by ID.

PUT /chat/id/{ownerType}/{ownerId}/{chatId}

Updates an existing chat channel and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

chatId: string
in path

Chat channel ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated chat channel.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this chat.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a chat channel by OID.

PUT /chat/{oid}

Updates an existing chat channel and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

oid: string
in path

Chat channel OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full chat channel record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated chat channel.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this chat.

404 Not Found

Not Found — chat does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Delete a chat channel by ID.

DELETE /chat/id/{ownerType}/{ownerId}/{chatId}

Removes the chat channel. Restore it with PUT /chat/undo-remove/id/{ownerType}/{ownerId}/{chatId} (or /chat/undo-remove/{oid}).

Returns 204 No Content, also when the channel does not exist.

ownerType: string
in path

Owner type. Currently only project is supported; other types return 400. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

chatId: string
in path

Chat channel ID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this chat.

Response Content-Types: application/json

Delete a chat channel by OID.

DELETE /chat/{oid}

Removes the chat channel. Restore it with PUT /chat/undo-remove/id/{ownerType}/{ownerId}/{chatId} (or /chat/undo-remove/{oid}).

Returns 204 No Content, also when the channel does not exist.

oid: string
in path

Chat channel OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this chat.

Response Content-Types: application/json

comment

A comment that a user can add to a chat channel or a task.

Add emoji reactions to a comment (by comment OID).

POST /comment/add-emoji/{commentOid}/{emojis}

Adds the caller's reactions with the given emojis. The request has no body; the emojis are in the URL path.

Only the emojis that Quire's reaction picker offers are accepted. Each can be given as the emoji itself or, more simply, by its name — the shortcode GitHub and Slack use — with or without colons and in any case: 😃 smiley, 😞 disappointed, 😐 neutral_face, 😂 joy, 😍 heart_eyes, 😜 stuck_out_tongue_winking_eye, 😏 smirk, 😱 scream, 😭 sob, 😡 rage (or pout), 👍 +1 (or thumbsup), 👎 -1 (or thumbsdown), 🙌 raised_hands, 👊 punch (or facepunch, fist_oncoming), 💪 muscle, ❤️ heart, 🎉 tada, 🚀 rocket, 💯 100, ⚠️ warning. ❤ and ⚠ without the variation selector (U+FE0F) are accepted as ❤️ and ⚠️. See also Emojis.

All or nothing: if any emoji is invalid, none is added and 400 is returned. Adding a reaction the caller already has is a no-op.

Anyone who can view the comment can react. A reaction always belongs to the authorizing user, never to the app. The comment's author is notified of each reaction added, except one the caller already had and one on the caller's own comment.

Returns 204 No Content. To see the reactions, read the comment with GET /comment/{commentOid}: its emojis lists each emoji with the users who reacted.

Example: POST /comment/add-emoji/iDsPd.QP_qM.hN.Trymukn8b/+1,tada adds 👍 and 🎉, and so does POST /comment/add-emoji/iDsPd.QP_qM.hN.Trymukn8b/%F0%9F%91%8D,%F0%9F%8E%89.

commentOid: string
in path

Comment OID.

emojis: string
in path

One or more emojis separated by commas, each as the emoji itself or its name (listed in the endpoint's description), percent-encoded. Names need no encoding, so prefer them, e.g. +1,tada. At most 20 per request. Duplicates and empty items are ignored.

204 No Content

No Content — reactions added (or already there).

400 Bad Request

Bad Request — an emoji or name is not accepted, none is given, or more than 20 are given.

403 Forbidden

Forbidden — caller can't view this comment.

404 Not Found

Not Found — comment does not exist.

Response Content-Types: application/json

Upload an attachment to a comment (by comment OID).

POST /comment/attach/{commentOid}/{filename}

Uploads an attachment to an existing comment.

Executable files (.exe, .com, .bat) are rejected unless the project has enabled uploading executable files.

A file larger than the plan allows, or one that would exceed the organization's storage quota, is rejected with 402 (code 469).

commentOid: string
in path

Comment OID.

filename: string
in path

Attachment file name, e.g., readme.txt.

Percent-encode it, e.g., My%20Report.pdf for My Report.pdf. It can't contain / or \.

Provide a meaningful extension so the browser can recognize the MIME type (e.g., revenue.pdf, contacts.json).

Alternatively, set the MIME type via the Content-Type header.

Request Example
"object"

OK — attachment record.

400 Bad Request

Bad Request — bad payload or filename, or an executable file is not allowed for this project.

402 Payment Required

Payment Required — the file exceeds the plan's file-size limit or the organization's storage quota (code 469).

403 Forbidden

Forbidden — caller lacks permission to attach to this comment.

404 Not Found

Not Found — comment does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
  "length": 20000,
  "name": "file.txt"
}

Add a new comment to a chat channel (by project ID and chat ID).

POST /comment/chat/id/{projectId}/{chatId}

Adds a new comment to the specified chat channel.

projectId: string
in path

Project ID.

chatId: string
in path

Chat channel ID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

Content of the new comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether to pin this comment. Default: false.

asUser: boolean

(Optional) If true, marks this comment as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). Either way, the authorizing user, not the app, follows the task or chat commented on.

Request Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}
200 OK

OK — created comment record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to add a comment to this chat channel.

404 Not Found

Not Found — chat channel does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Add a new comment to a chat channel (by chat OID).

POST /comment/chat/{chatOid}

Adds a new comment to the specified chat channel.

chatOid: string
in path

OID of the chat channel.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

Content of the new comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether to pin this comment. Default: false.

asUser: boolean

(Optional) If true, marks this comment as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). Either way, the authorizing user, not the app, follows the task or chat commented on.

Request Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}
200 OK

OK — created comment record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to add a comment to this chat channel.

404 Not Found

Not Found — chat channel does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Add a new comment to a task (by task OID).

POST /comment/{taskOid}

Adds a new comment to the specified task.

taskOid: string
in path

OID of the task.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

Content of the new comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether to pin this comment. Default: false.

asUser: boolean

(Optional) If true, marks this comment as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). Either way, the authorizing user, not the app, follows the task or chat commented on.

Request Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}
200 OK

OK — created comment record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to add a comment to this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Add a new comment to a task (by project ID and task ID).

POST /comment/id/{projectId}/{taskId}

Adds a new comment to the specified task.

projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

Content of the new comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether to pin this comment. Default: false.

asUser: boolean

(Optional) If true, marks this comment as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). Either way, the authorizing user, not the app, follows the task or chat commented on.

Request Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}
200 OK

OK — created comment record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to add a comment to this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get an existing comment (by comment OID).

GET /comment/{commentOid}

Returns the full comment record.

commentOid: string
in path

Comment OID.

200 OK

OK — comment record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — comment does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get all comments of a chat channel (by project ID and chat ID).

GET /comment/list/chat/id/{projectId}/{chatId}

Returns the comments of the specified chat channel.

All of them come in one response, with no paging: pinned comments first, most recently pinned first, then the rest, newest first. Deleted comments are left out.

projectId: string
in path

Project ID.

chatId: string
in path

Chat channel ID.

200 OK

OK — list of comments (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — chat channel does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "description": "It is *cool*!",
    "descriptionText": "It is cool!",
    "descriptionHtml": "It is <i>cool</i>!",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "emojis": [
      {
        "emoji": "👍",
        "users": [
          "#/definitions/SimpleIdentity"
        ]
      }
    ],
    "url": "string",
    "pinBy": "#/definitions/SimpleIdentity",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "pinAt": "2018-12-22T02:06:58.158Z",
    "editedBy": "#/definitions/SimpleIdentity",
    "owner": {
      "url": "https://quire.io/w/my_project/42",
      "id": "42",
      "type": "Task",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Get all comments of a chat channel (by chat OID).

GET /comment/list/chat/{chatOid}

Returns the comments of the specified chat channel.

All of them come in one response, with no paging: pinned comments first, most recently pinned first, then the rest, newest first. Deleted comments are left out.

chatOid: string
in path

OID of the chat channel.

200 OK

OK — list of comments (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — chat channel does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "description": "It is *cool*!",
    "descriptionText": "It is cool!",
    "descriptionHtml": "It is <i>cool</i>!",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "emojis": [
      {
        "emoji": "👍",
        "users": [
          "#/definitions/SimpleIdentity"
        ]
      }
    ],
    "url": "string",
    "pinBy": "#/definitions/SimpleIdentity",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "pinAt": "2018-12-22T02:06:58.158Z",
    "editedBy": "#/definitions/SimpleIdentity",
    "owner": {
      "url": "https://quire.io/w/my_project/42",
      "id": "42",
      "type": "Task",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Get all comments of a task (by project ID and task ID).

GET /comment/list/id/{projectId}/{taskId}

Returns the comments of the specified task.

All of them come in one response, with no paging: pinned comments first, most recently pinned first, then the rest, newest first. Deleted comments are left out.

projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

200 OK

OK — list of comments (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "description": "It is *cool*!",
    "descriptionText": "It is cool!",
    "descriptionHtml": "It is <i>cool</i>!",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "emojis": [
      {
        "emoji": "👍",
        "users": [
          "#/definitions/SimpleIdentity"
        ]
      }
    ],
    "url": "string",
    "pinBy": "#/definitions/SimpleIdentity",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "pinAt": "2018-12-22T02:06:58.158Z",
    "editedBy": "#/definitions/SimpleIdentity",
    "owner": {
      "url": "https://quire.io/w/my_project/42",
      "id": "42",
      "type": "Task",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Get all comments of a task (by task OID).

GET /comment/list/{taskOid}

Returns the comments of the specified task.

All of them come in one response, with no paging: pinned comments first, most recently pinned first, then the rest, newest first. Deleted comments are left out.

taskOid: string
in path

OID of the task.

200 OK

OK — list of comments (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "description": "It is *cool*!",
    "descriptionText": "It is cool!",
    "descriptionHtml": "It is <i>cool</i>!",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "emojis": [
      {
        "emoji": "👍",
        "users": [
          "#/definitions/SimpleIdentity"
        ]
      }
    ],
    "url": "string",
    "pinBy": "#/definitions/SimpleIdentity",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "pinAt": "2018-12-22T02:06:58.158Z",
    "editedBy": "#/definitions/SimpleIdentity",
    "owner": {
      "url": "https://quire.io/w/my_project/42",
      "id": "42",
      "type": "Task",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Undo the removal of a comment (by comment OID).

PUT /comment/undo-remove/{commentOid}

Restores a previously-removed comment. Idempotent: if the comment is not currently removed, this is a no-op and returns the current comment record.

Anyone can edit, delete or restore their own comment. Doing so to someone else's needs edit access to the project (with Edit with limitations, or as a guest, you can do so only to your own) and, if the author is a project member, the project (or chat channel) must allow editing comments posted by other members, which is the default. External team members can never do so to a project member's comment. Otherwise 403.

commentOid: string
in path

Comment OID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

200 OK

OK — restored comment record.

403 Forbidden

Forbidden — caller lacks permission to restore this comment.

404 Not Found

Not Found — comment does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update an existing comment (by comment OID).

PUT /comment/{commentOid}

Updates an existing comment and returns the updated record.

Anyone can edit, delete or restore their own comment. Doing so to someone else's needs edit access to the project (with Edit with limitations, or as a guest, you can do so only to your own) and, if the author is a project member, the project (or chat channel) must allow editing comments posted by other members, which is the default. External team members can never do so to a project member's comment. Otherwise 403.

Pinning or unpinning someone else's comment (sending pinned alone) needs only edit access to the project, whatever the setting.

commentOid: string
in path

Comment OID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full comment record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) New comment content (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether the comment is pinned.

asUser: boolean

(Optional) If true, the app, not the authorizing user, is recorded as the one who made this change: editedBy when description is changed, and pinBy when the comment is pinned. Default: false.

Request Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}
200 OK

OK — updated comment record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller can't edit or pin this comment.

404 Not Found

Not Found — comment does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Remove emoji reactions from a comment (by comment OID).

DELETE /comment/remove-emoji/{commentOid}/{emojis}

Removes the caller's reactions with the given emojis. The request has no body; the emojis are in the URL path.

Each can be given as the emoji itself or by its name, with or without colons and in any case: 😃 smiley, 😞 disappointed, 😐 neutral_face, 😂 joy, 😍 heart_eyes, 😜 stuck_out_tongue_winking_eye, 😏 smirk, 😱 scream, 😭 sob, 😡 rage (or pout), 👍 +1 (or thumbsup), 👎 -1 (or thumbsdown), 🙌 raised_hands, 👊 punch (or facepunch, fist_oncoming), 💪 muscle, ❤️ heart, 🎉 tada, 🚀 rocket, 💯 100, ⚠️ warning. ❤ and ⚠ without the variation selector (U+FE0F) are taken as ❤️ and ⚠️. Any other non-empty value is accepted too, so a reaction with an emoji the picker no longer offers can still be removed. See also Emojis.

Removing a reaction the caller doesn't have is a no-op.

Returns 204 No Content. To see the remaining reactions, read the comment with GET /comment/{commentOid}.

Note: Like deleting a comment, returns 204 No Content regardless of whether the comment exists. If it doesn't, or it has been deleted, nothing is changed.

Example: DELETE /comment/remove-emoji/iDsPd.QP_qM.hN.Trymukn8b/+1 removes the caller's 👍.

commentOid: string
in path

Comment OID.

emojis: string
in path

One or more emojis separated by commas, each as the emoji itself or its name (listed in the endpoint's description), percent-encoded. Names need no encoding, so prefer them, e.g. +1,tada. At most 20 per request. Duplicates and empty items are ignored.

204 No Content

No Content — reactions removed (or already absent, or no such comment).

400 Bad Request

Bad Request — no emoji is given, or more than 20 are given.

403 Forbidden

Forbidden — caller can't view this comment.

Response Content-Types: application/json

Delete an existing comment (by comment OID).

DELETE /comment/{commentOid}

Deletes an existing comment. Restore it with PUT /comment/undo-remove/{commentOid}.

Anyone can edit, delete or restore their own comment. Doing so to someone else's needs edit access to the project (with Edit with limitations, or as a guest, you can do so only to your own) and, if the author is a project member, the project (or chat channel) must allow editing comments posted by other members, which is the default. External team members can never do so to a project member's comment. Otherwise 403.

Note: Returns 204 No Content regardless of whether the comment exists.

commentOid: string
in path

Comment OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller can't delete this comment.

Response Content-Types: application/json

dashboard

Dashboards — a dashboard groups widgets that visualize the data of a project, organization, folder, or smart folder. These endpoints manage the dashboard itself (create, read, update, archive, remove, and restore); the widgets shown on a dashboard are not yet manageable through the public API.

Create a dashboard by owner OID.

POST /dashboard/{ownerType}/{ownerOid}

Adds a new dashboard to the specified owner (project, organization, folder, or smart-folder) and returns it.

Creates the dashboard container only (name, description, icon, etc.); the widgets shown on the dashboard cannot be set through the API yet.

Example — POST /dashboard/id/project/my_project:

{
  "name": "Team overview",
  "image": "icon-view-dashboard"
}

Returns 402 if the plan's dashboard limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /abc123 is equivalent to /project/abc123.

ownerOid: string
in path

Owner OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created dashboard record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — dashboard quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a dashboard under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create a dashboard by owner ID.

POST /dashboard/id/{ownerType}/{ownerId}

Adds a new dashboard to the specified owner (project, organization, folder, or smart-folder) and returns it.

Creates the dashboard container only (name, description, icon, etc.); the widgets shown on the dashboard cannot be set through the API yet.

Example — POST /dashboard/id/project/my_project:

{
  "name": "Team overview",
  "image": "icon-view-dashboard"
}

Returns 402 if the plan's dashboard limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/foo is equivalent to /id/project/foo.

ownerId: string
in path

Owner ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created dashboard record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — dashboard quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a dashboard under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a dashboard by ID.

GET /dashboard/id/{ownerType}/{ownerId}/{dashboardId}

Returns the full dashboard record for the given owner and dashboard ID.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/dashboard1 is equivalent to /id/project/my_project/dashboard1.

ownerId: string
in path

Owner ID.

dashboardId: string
in path

Dashboard ID.

200 OK

OK — dashboard record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — dashboard or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a dashboard by OID.

GET /dashboard/{oid}

Returns the full dashboard record.

oid: string
in path

Dashboard OID.

200 OK

OK — dashboard record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — dashboard does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List dashboards by owner ID.

GET /dashboard/list/id/{ownerType}/{ownerId}

Returns the owner's dashboards that the caller can see; one shown to selected members only is left out for the others. Archived dashboards are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/id/foo is equivalent to /list/id/project/foo.

ownerId: string
in path

Owner ID.

200 OK

OK — list of dashboard records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?dashboard=Board101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List dashboards by owner OID.

GET /dashboard/list/{ownerType}/{ownerOid}

Returns the owner's dashboards that the caller can see; one shown to selected members only is left out for the others. Archived dashboards are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/abc123 is equivalent to /list/project/abc123.

ownerOid: string
in path

Owner OID.

200 OK

OK — list of dashboard records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?dashboard=Board101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Undo the removal of a dashboard by ID.

PUT /dashboard/undo-remove/id/{ownerType}/{ownerId}/{dashboardId}

Restores a previously-removed dashboard. Idempotent: if the dashboard is not currently removed, this is a no-op and returns the current dashboard record.

Subject to the dashboard-per-owner quota: may return 402 Payment Required if the plan's dashboard limit is already reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /undo-remove/id/foo/bar is equivalent to /undo-remove/id/project/foo/bar.

ownerId: string
in path

Owner ID.

dashboardId: string
in path

Dashboard ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored dashboard record.

402 Payment Required

Payment Required — dashboard quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this dashboard.

404 Not Found

Not Found — dashboard or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of a dashboard by OID.

PUT /dashboard/undo-remove/{oid}

Restores a previously-removed dashboard. Idempotent: if the dashboard is not currently removed, this is a no-op and returns the current dashboard record.

Subject to the dashboard-per-owner quota: may return 402 Payment Required if the plan's dashboard limit is already reached.

oid: string
in path

OID of the dashboard to restore.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored dashboard record.

402 Payment Required

Payment Required — dashboard quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this dashboard.

404 Not Found

Not Found — dashboard does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a dashboard by ID.

PUT /dashboard/id/{ownerType}/{ownerId}/{dashboardId}

Updates an existing dashboard and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

Updates the dashboard container only; the widgets shown on the dashboard cannot be changed through the API yet.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/dashboard1 is equivalent to /id/project/my_project/dashboard1.

ownerId: string
in path

Owner ID.

dashboardId: string
in path

Dashboard ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated dashboard record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this dashboard.

404 Not Found

Not Found — dashboard or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a dashboard by OID.

PUT /dashboard/{oid}

Updates an existing dashboard and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

Updates the dashboard container only; the widgets shown on the dashboard cannot be changed through the API yet.

oid: string
in path

Dashboard OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full dashboard record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated dashboard record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this dashboard.

404 Not Found

Not Found — dashboard does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Delete a dashboard by ID.

DELETE /dashboard/id/{ownerType}/{ownerId}/{dashboardId}

Removes the dashboard. Restore it with PUT /dashboard/undo-remove/id/{ownerType}/{ownerId}/{dashboardId} (or /dashboard/undo-remove/{oid}).

Returns 204 No Content, also when the dashboard does not exist.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/dashboard1 is equivalent to /id/project/my_project/dashboard1.

ownerId: string
in path

Owner ID.

dashboardId: string
in path

Dashboard ID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this dashboard.

Response Content-Types: application/json

Delete a dashboard by OID.

DELETE /dashboard/{oid}

Removes the dashboard. Restore it with PUT /dashboard/undo-remove/id/{ownerType}/{ownerId}/{dashboardId} (or /dashboard/undo-remove/{oid}).

Returns 204 No Content, also when the dashboard does not exist.

oid: string
in path

Dashboard OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this dashboard.

Response Content-Types: application/json

doc

Documents.

doc

Create a document by owner OID.

POST /doc/{ownerType}/{ownerOid}

Adds a new document to the specified owner (project, organization, folder, or smart-folder) and returns it.

Example — POST /doc/id/project/my_project:

{
  "name": "Release notes",
  "description": "What changed in **v2.0**.",
  "followers": ["me"]
}

followers is allowed only when the owner is a project.

Returns 402 if the plan's document limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /abc123 is equivalent to /project/abc123.

ownerOid: string
in path

Owner OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

followers: string[]

(Optional) Users (OID, ID, or email) who follow this document. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK
Doc

OK — created doc record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — document quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a doc in this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Create a document by owner ID.

POST /doc/id/{ownerType}/{ownerId}

Adds a new document to the specified owner (project, organization, folder, or smart-folder) and returns it.

Example — POST /doc/id/project/my_project:

{
  "name": "Release notes",
  "description": "What changed in **v2.0**.",
  "followers": ["me"]
}

followers is allowed only when the owner is a project.

Returns 402 if the plan's document limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/foo is equivalent to /id/project/foo.

ownerId: string
in path

Owner ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

followers: string[]

(Optional) Users (OID, ID, or email) who follow this document. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK
Doc

OK — created doc record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — document quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a doc in this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Get a document by ID.

GET /doc/id/{ownerType}/{ownerId}/{docId}

Returns the full document record for the given owner and document ID.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

docId: string
in path

Document ID.

200 OK
Doc

OK — doc record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Get a document by OID.

GET /doc/{oid}

Returns the full document record.

oid: string
in path

Document OID.

200 OK
Doc

OK — doc record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

List documents by owner ID.

GET /doc/list/id/{ownerType}/{ownerId}

Returns the owner's documents that the caller can see; one shown to selected members only is left out for the others. Archived documents are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/id/foo is equivalent to /list/id/project/foo.

ownerId: string
in path

Owner ID.

200 OK
Doc

OK — list of doc records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?doc=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "mutes": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "members": [
      "#/definitions/SimpleIdentity"
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]
doc

List documents by owner OID.

GET /doc/list/{ownerType}/{ownerOid}

Returns the owner's documents that the caller can see; one shown to selected members only is left out for the others. Archived documents are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/abc123 is equivalent to /list/project/abc123.

ownerOid: string
in path

Owner OID.

200 OK
Doc

OK — list of doc records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?doc=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "mutes": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "members": [
      "#/definitions/SimpleIdentity"
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]
doc

Undo the removal of a document by ID.

PUT /doc/undo-remove/id/{ownerType}/{ownerId}/{docId}

Restores a previously-removed document. Idempotent: if the document is not currently removed, this is a no-op and returns the current document record.

Subject to the document-per-owner quota: may return 402 Payment Required if the plan's document limit is already reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /undo-remove/id/foo/bar is equivalent to /undo-remove/id/project/foo/bar.

ownerId: string
in path

Owner ID.

docId: string
in path

Document ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK
Doc

OK — restored doc record.

402 Payment Required

Payment Required — document quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this doc.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Undo the removal of a document by OID.

PUT /doc/undo-remove/{oid}

Restores a previously-removed document. Idempotent: if the document is not currently removed, this is a no-op and returns the current document record.

Subject to the document-per-owner quota: may return 402 Payment Required if the plan's document limit is already reached.

oid: string
in path

OID of the document to restore.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK
Doc

OK — restored doc record.

402 Payment Required

Payment Required — document quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this doc.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Update a document by ID.

PUT /doc/id/{ownerType}/{ownerId}/{docId}

Updates an existing document and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

docId: string
in path

Document ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers. Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK
Doc

OK — updated doc record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this doc.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Update a document by OID.

PUT /doc/{oid}

Updates an existing document and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

oid: string
in path

Document OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full document record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers. Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK
Doc

OK — updated doc record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this doc.

404 Not Found

Not Found — doc does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
doc

Delete a document by ID.

DELETE /doc/id/{ownerType}/{ownerId}/{docId}

Removes the document. Restore it with PUT /doc/undo-remove/id/{ownerType}/{ownerId}/{docId} (or /doc/undo-remove/{oid}).

Returns 204 No Content, also when the document does not exist.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

Owner ID.

docId: string
in path

Document ID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this doc.

Response Content-Types: application/json
doc

Delete a document by OID.

DELETE /doc/{oid}

Removes the document. Restore it with PUT /doc/undo-remove/id/{ownerType}/{ownerId}/{docId} (or /doc/undo-remove/{oid}).

Returns 204 No Content, also when the document does not exist.

oid: string
in path

Document OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this doc.

Response Content-Types: application/json

insight

Insight views — configurable task views with filters and columns.

Add a custom-field definition to an insight view by ID.

POST /insight/add-field/id/{ownerType}/{ownerId}/{insightId}

Adds a custom-field definition to the insight view.

Only formula and lookup types are allowed on insight views; any other type returns 400, as do an invalid body and a missing name.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

A name already in use returns 409; reaching the plan's custom-field limit returns 402.

ownerType: string project, organization, folder, smart-folder
in path

Owner type of the insight. Required here: it is not assumed to be project.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(Optional, select only) Options, each an object with name and an optional color — not a plain string. Example: [{"name": "High", "color": "13"}, {"name": "Low"}].

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date, number, money, duration, lookup, and formula fields whose resultType resolves to one of those.

name: string

Unique name for this field. Must be a non-empty string of at most 1,280 characters, and must not contain }, ", or \.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "name": "Priority",
  "type": "number"
}

OK — created field definition.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — custom-field quota reached.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight or owner does not exist.

409 Conflict

Conflict — a field with this name already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Add a custom-field definition to an insight view.

POST /insight/add-field/{oid}

Adds a custom-field definition to the insight view.

Only formula and lookup types are allowed on insight views; any other type returns 400, as do an invalid body and a missing name.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

A name already in use returns 409; reaching the plan's custom-field limit returns 402.

oid: string
in path

Insight OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(Optional, select only) Options, each an object with name and an optional color — not a plain string. Example: [{"name": "High", "color": "13"}, {"name": "Low"}].

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date, number, money, duration, lookup, and formula fields whose resultType resolves to one of those.

name: string

Unique name for this field. Must be a non-empty string of at most 1,280 characters, and must not contain }, ", or \.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "name": "Priority",
  "type": "number"
}

OK — created field definition.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — custom-field quota reached.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight does not exist.

409 Conflict

Conflict — a field with this name already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Create an insight view by owner OID.

POST /insight/{ownerType}/{ownerOid}

Adds a new insight view to the specified owner (project, organization, folder, or smart-folder) and returns it.

Example — POST /insight/id/project/my_project:

{
  "name": "Workload",
  "image": "icon-view-insight"
}

To add formula or lookup columns, call POST /insight/add-field/id/{ownerType}/{ownerId}/{insightId} afterwards.

Returns 402 if the plan's insight limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /abc123 is equivalent to /project/abc123.

ownerOid: string
in path

Owner OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created insight record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — insight quota reached.

403 Forbidden

Forbidden — caller lacks permission to create an insight under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create an insight view by owner ID.

POST /insight/id/{ownerType}/{ownerId}

Adds a new insight view to the specified owner (project, organization, folder, or smart-folder) and returns it.

Example — POST /insight/id/project/my_project:

{
  "name": "Workload",
  "image": "icon-view-insight"
}

To add formula or lookup columns, call POST /insight/add-field/id/{ownerType}/{ownerId}/{insightId} afterwards.

Returns 402 if the plan's insight limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/foo is equivalent to /id/project/foo.

ownerId: string
in path

Owner ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created insight record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — insight quota reached.

403 Forbidden

Forbidden — caller lacks permission to create an insight under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Run an Insight and return its computed result (by ID).

GET /insight/run/id/{ownerType}/{ownerId}/{insightId}

Runs the Insight and returns its computed result — one aggregated row per group, as a JSON 2D array. The Insight's formulas and its column layout (set in Quire; the layout is not exposed through the API) drive what's evaluated.

Response shape: [[<headers>], [<row>], ...]. Row 0 is the column-label header row; the first column is the synthesized group-by column (assignee for ?group-by=member, section for ?group-by=section); remaining columns are the Insight's columns as laid out in Quire, without the custom fields the caller can't view. Header labels are raw field-name strings (locale-independent), matching /task/list, /search/*, and export-json.

Example (group-by=section, two sections plus one sectionless task; score is a project number field, f1 an Insight formula field):

[
  ["section", "name", "priority", "score", "f1"],
  [{"oid":"T1","id":7,"name":"Backend"}, null, 2, 30, 63],
  [{"oid":"T2","id":8,"name":"Frontend"}, null, 1, 70, 142],
  [null, null, 2, 50, 102]
]

Row order: alphabetical by the group entity's name (case-insensitive, simple-markdown stripped); null group (unassigned / sectionless tasks) sorts last.

Aggregation per column is driven by the field's calc type (the field's default, or the calculation chosen for the column in Quire):

  • name → null (no aggregation; not applicable)
  • status → avg, priority → max
  • start → min, due / completedAt → max
  • a number, money, duration or lookup field → sum
  • a date field → max
  • a formula field → sum (default)

Cell value types (how to parse each cell):

  • text / number / boolean → as-is JSON.
  • date (start, due or a date field) → yyyy-MM-dd when it has no time, otherwise an ISO-8601 UTC datetime (2026-06-20T09:00:00Z).
  • money (a money field) → the numeric amount only (currency symbol and decimal count are dropped).
  • duration (a duration field) and time-log totals → an integer number of seconds.
  • entity (member / section / task ref) → {oid, id, name}; a user's id is a string, a task's / section's id is an integer; name is plain text (markdown stripped). Deleted-user assignees become a censored placeholder so their group stays distinct from the unassigned (null) group.
  • null → empty / not applicable (e.g. the name column on an aggregated row, or a column with no value for the group).

Project-scoped Insights only. Other owner types return 400.

Formula-token limitation: the project's task collections — project.tasks, project.activetasks, project.completedtasks (and project.subtasks, which means project.tasks) — are not supported through this endpoint, in an Insight's formula field and in a project's formula field alike. Evaluating any of them would scan every task in the project, which is deliberately not exposed on the public API. Cells that reference them render as JSON null; the rest of the row is unaffected. Workarounds:

  • Reference the row's own task fields (e.g. priority, due, or a project's number field).
  • Use the row task's subtasks (or activesubtasks / completedsubtasks) to walk its children; these are supported.

Rate-limit cost: max(1, ceil(tasks / 250)) units, where tasks is the number of tasks loaded after the ?status= filter — 1 for up to 250 tasks, 4 for 1,000. A narrower ?status= costs less. See also Rate Limits.

ownerType: string project
in path

Owner type. Only project is supported on this endpoint; other types return 400.

ownerId: string
in path

Project ID (the owner ID).

insightId: string
in path

Insight ID.

group-by: string member, section member
in query

(Optional) Row grouping. member produces one row per assignee (multi-assignee tasks contribute to every group their assignees are in; unassigned tasks fall into a null group). section produces one row per section ancestor (tasks not under any section fall into a null group). Case-insensitive.

status: string active, completed, all active
in query

(Optional) Task-state filter, applied at the SQL load layer (narrower queries cost less — see rate-limit note). active = not-yet-completed tasks (state < completed). completed = completed tasks. all = no filter. Case-insensitive.

200 OK

OK — JSON 2D array (header row + data rows; data rows may be empty).

400 Bad Request

Bad Request — unknown ?group-by / ?status value, or non-project-scoped Insight.

403 Forbidden

Forbidden — caller lacks read permission on the Insight.

404 Not Found

Not Found — Insight or owner does not exist.

429 Too Many Requests

Too Many Requests — rate-limit exceeded.

Response Content-Types: application/json

Run an Insight and return its computed result (by OID).

GET /insight/run/{oid}

Runs the Insight and returns its computed result — one aggregated row per group, as a JSON 2D array. The Insight's formulas and its column layout (set in Quire; the layout is not exposed through the API) drive what's evaluated.

Response shape: [[<headers>], [<row>], ...]. Row 0 is the column-label header row; the first column is the synthesized group-by column (assignee for ?group-by=member, section for ?group-by=section); remaining columns are the Insight's columns as laid out in Quire, without the custom fields the caller can't view. Header labels are raw field-name strings (locale-independent), matching /task/list, /search/*, and export-json.

Example (group-by=section, two sections plus one sectionless task; score is a project number field, f1 an Insight formula field):

[
  ["section", "name", "priority", "score", "f1"],
  [{"oid":"T1","id":7,"name":"Backend"}, null, 2, 30, 63],
  [{"oid":"T2","id":8,"name":"Frontend"}, null, 1, 70, 142],
  [null, null, 2, 50, 102]
]

Row order: alphabetical by the group entity's name (case-insensitive, simple-markdown stripped); null group (unassigned / sectionless tasks) sorts last.

Aggregation per column is driven by the field's calc type (the field's default, or the calculation chosen for the column in Quire):

  • name → null (no aggregation; not applicable)
  • status → avg, priority → max
  • start → min, due / completedAt → max
  • a number, money, duration or lookup field → sum
  • a date field → max
  • a formula field → sum (default)

Cell value types (how to parse each cell):

  • text / number / boolean → as-is JSON.
  • date (start, due or a date field) → yyyy-MM-dd when it has no time, otherwise an ISO-8601 UTC datetime (2026-06-20T09:00:00Z).
  • money (a money field) → the numeric amount only (currency symbol and decimal count are dropped).
  • duration (a duration field) and time-log totals → an integer number of seconds.
  • entity (member / section / task ref) → {oid, id, name}; a user's id is a string, a task's / section's id is an integer; name is plain text (markdown stripped). Deleted-user assignees become a censored placeholder so their group stays distinct from the unassigned (null) group.
  • null → empty / not applicable (e.g. the name column on an aggregated row, or a column with no value for the group).

Project-scoped Insights only. Other owner types return 400.

Formula-token limitation: the project's task collections — project.tasks, project.activetasks, project.completedtasks (and project.subtasks, which means project.tasks) — are not supported through this endpoint, in an Insight's formula field and in a project's formula field alike. Evaluating any of them would scan every task in the project, which is deliberately not exposed on the public API. Cells that reference them render as JSON null; the rest of the row is unaffected. Workarounds:

  • Reference the row's own task fields (e.g. priority, due, or a project's number field).
  • Use the row task's subtasks (or activesubtasks / completedsubtasks) to walk its children; these are supported.

Rate-limit cost: max(1, ceil(tasks / 250)) units, where tasks is the number of tasks loaded after the ?status= filter — 1 for up to 250 tasks, 4 for 1,000. A narrower ?status= costs less. See also Rate Limits.

oid: string
in path

Insight OID.

group-by: string member, section member
in query

(Optional) Row grouping. member produces one row per assignee (multi-assignee tasks contribute to every group their assignees are in; unassigned tasks fall into a null group). section produces one row per section ancestor (tasks not under any section fall into a null group). Case-insensitive.

status: string active, completed, all active
in query

(Optional) Task-state filter, applied at the SQL load layer (narrower queries cost less — see rate-limit note). active = not-yet-completed tasks (state < completed). completed = completed tasks. all = no filter. Case-insensitive.

200 OK

OK — JSON 2D array (header row + data rows; data rows may be empty).

400 Bad Request

Bad Request — unknown ?group-by / ?status value, or non-project-scoped Insight.

403 Forbidden

Forbidden — caller lacks read permission on the Insight.

404 Not Found

Not Found — Insight does not exist.

429 Too Many Requests

Too Many Requests — rate-limit exceeded.

Response Content-Types: application/json

Get an insight view by ID.

GET /insight/id/{ownerType}/{ownerId}/{insightId}

Returns the full insight record for the given owner and insight ID.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/insight1 is equivalent to /id/project/my_project/insight1.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

200 OK

OK — insight record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — insight or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get an insight view by OID.

GET /insight/{oid}

Returns the full insight record.

oid: string
in path

Insight OID.

200 OK

OK — insight record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — insight does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List insight views by owner ID.

GET /insight/list/id/{ownerType}/{ownerId}

Returns the owner's insight views that the caller can see; one shown to selected members only is left out for the others. Archived ones are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/id/foo is equivalent to /list/id/project/foo.

ownerId: string
in path

Owner ID.

200 OK

OK — list of insight records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?insight=View101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "fields": "object",
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List insight views by owner OID.

GET /insight/list/{ownerType}/{ownerOid}

Returns the owner's insight views that the caller can see; one shown to selected members only is left out for the others. Archived ones are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /list/abc123 is equivalent to /list/project/abc123.

ownerOid: string
in path

Owner OID.

200 OK

OK — list of insight records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?insight=View101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "fields": "object",
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Reorder a custom-field definition on an insight view by ID.

PUT /insight/move-field/id/{ownerType}/{ownerId}/{insightId}

Moves the named field to a new position. By default the field is moved to the end; pass &before={otherName} to place it immediately before another field.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

A missing field, or a missing &before={otherName} field, returns 404; a missing name query parameter, 400.

ownerType: string project, organization, folder, smart-folder
in path

Owner type of the insight. Required here: it is not assumed to be project.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

name: string
in query

Name of the field to move. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

before: string
in query

(Optional) Name of the field to insert before. If omitted, the field is moved to the end. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

OK — moved field definition.

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight, owner, field or before field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Reorder a custom-field definition on an insight view.

PUT /insight/move-field/{oid}

Moves the named field to a new position. By default the field is moved to the end; pass &before={otherName} to place it immediately before another field.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

A missing field, or a missing &before={otherName} field, returns 404; a missing name query parameter, 400.

oid: string
in path

Insight OID.

name: string
in query

Name of the field to move. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

before: string
in query

(Optional) Name of the field to insert before. If omitted, the field is moved to the end. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

OK — moved field definition.

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight, field or before field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Rename a custom-field definition on an insight view by ID.

PUT /insight/rename-field/id/{ownerType}/{ownerId}/{insightId}

Renames the field in place and returns the renamed field. The field's content is preserved.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition plus its new name; with ?return=compact, only {"name": "<new name>"}.

A missing field returns 404; a new-name already in use, 409; a missing name or new-name, or an invalid new-name, 400 — new-name must be non-empty, without }, " or \, and at most 1,280 characters.

ownerType: string project, organization, folder, smart-folder
in path

Owner type of the insight. Required here: it is not assumed to be project.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

name: string
in query

Current field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

new-name: string
in query

New field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

OK — renamed field definition.

400 Bad Request

Bad Request — name or new-name missing, or new-name invalid.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight, owner or field does not exist.

409 Conflict

Conflict — new-name is already in use.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Rename a custom-field definition on an insight view.

PUT /insight/rename-field/{oid}

Renames the field in place and returns the renamed field. The field's content is preserved.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition plus its new name; with ?return=compact, only {"name": "<new name>"}.

A missing field returns 404; a new-name already in use, 409; a missing name or new-name, or an invalid new-name, 400 — new-name must be non-empty, without }, " or \, and at most 1,280 characters.

oid: string
in path

Insight OID.

name: string
in query

Current field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

new-name: string
in query

New field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

OK — renamed field definition.

400 Bad Request

Bad Request — name or new-name missing, or new-name invalid.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight or field does not exist.

409 Conflict

Conflict — new-name is already in use.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Undo the removal of an insight view by ID.

PUT /insight/undo-remove/id/{ownerType}/{ownerId}/{insightId}

Restores a previously-removed insight view. Idempotent: if the insight is not currently removed, this is a no-op and returns the current insight record.

Subject to the insight-per-owner quota: may return 402 Payment Required if the plan's insight limit is already reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /undo-remove/id/foo/bar is equivalent to /undo-remove/id/project/foo/bar.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored insight record.

402 Payment Required

Payment Required — insight quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this insight.

404 Not Found

Not Found — insight or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of an insight view by OID.

PUT /insight/undo-remove/{oid}

Restores a previously-removed insight view. Idempotent: if the insight is not currently removed, this is a no-op and returns the current insight record.

Subject to the insight-per-owner quota: may return 402 Payment Required if the plan's insight limit is already reached.

oid: string
in path

OID of the insight to restore.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored insight record.

402 Payment Required

Payment Required — insight quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this insight.

404 Not Found

Not Found — insight does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a custom-field definition on an insight view by ID.

PUT /insight/update-field/id/{ownerType}/{ownerId}/{insightId}

Updates the content of an existing custom field of the insight view.

type is immutable — if supplied, it must match the existing type, or 400. Keys that are omitted leave their current values intact, and so does each boolean option you omit or send as null (hidden, locked, private, …): they are merged one by one, not replaced as a set. An invalid body or a missing name query parameter returns 400; a missing field, 404.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

To rename a field, use /insight/rename-field/id/{ownerType}/{ownerId}/{insightId}?name={fieldName}&new-name={newName}; to reorder, use /insight/move-field/id/{ownerType}/{ownerId}/{insightId}?name={fieldName}. (The /{oid} URL form, e.g. /insight/rename-field/{oid}?…, is also accepted.)

ownerType: string project, organization, folder, smart-folder
in path

Owner type of the insight. Required here: it is not assumed to be project.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

name: string
in query

Name of the field to update. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. Pass $ to reset a money field to its default.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: UpdateFieldOption

(Optional, select only) Replacement option list, each an object with name, an optional color, and an optional from. It replaces the entire set; [] removes every option. To rename an option, give its current name in from, e.g. {"name": "Critical", "from": "High"}; tasks set to it get the new name. Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches (by from, else by name).

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity. Replaces the entire map.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys.

conditionFormat: FieldConditionFormat

(Optional) Replacement conditional-format rules. It replaces the entire list; [] removes every rule.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

(Optional) Field type. Immutable on update — if supplied, must match the existing field's type. Usually omitted; include only to verify the stored type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "from": "High",
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

OK — updated field definition.

400 Bad Request

Bad Request — body validation failed, or name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight, owner or field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Update a custom-field definition on an insight view.

PUT /insight/update-field/{oid}

Updates the content of an existing custom field of the insight view.

type is immutable — if supplied, it must match the existing type, or 400. Keys that are omitted leave their current values intact, and so does each boolean option you omit or send as null (hidden, locked, private, …): they are merged one by one, not replaced as a set. An invalid body or a missing name query parameter returns 400; a missing field, 404.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns the field's definition (the shape of an entry in the insight's fields) plus its name; with ?return=compact, only {"name": "…"}.

To rename a field, use /insight/rename-field/id/{ownerType}/{ownerId}/{insightId}?name={fieldName}&new-name={newName}; to reorder, use /insight/move-field/id/{ownerType}/{ownerId}/{insightId}?name={fieldName}. (The /{oid} URL form, e.g. /insight/rename-field/{oid}?…, is also accepted.)

oid: string
in path

Insight OID.

name: string
in query

Name of the field to update. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the field's definition plus its name; compact returns only {"name": "…"} (for rename, the new name). Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. Pass $ to reset a money field to its default.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: UpdateFieldOption

(Optional, select only) Replacement option list, each an object with name, an optional color, and an optional from. It replaces the entire set; [] removes every option. To rename an option, give its current name in from, e.g. {"name": "Critical", "from": "High"}; tasks set to it get the new name. Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches (by from, else by name).

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity. Replaces the entire map.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys.

conditionFormat: FieldConditionFormat

(Optional) Replacement conditional-format rules. It replaces the entire list; [] removes every rule.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

(Optional) Field type. Immutable on update — if supplied, must match the existing field's type. Usually omitted; include only to verify the stored type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "from": "High",
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

OK — updated field definition.

400 Bad Request

Bad Request — body validation failed, or name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — insight or field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Update an insight view by ID.

PUT /insight/id/{ownerType}/{ownerId}/{insightId}

Updates an existing insight view and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/insight1 is equivalent to /id/project/my_project/insight1.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated insight record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this insight.

404 Not Found

Not Found — insight or owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update an insight view by OID.

PUT /insight/{oid}

Updates an existing insight view and returns the updated record.

To archive or unarchive, set archived: true or archived: false in the body.

oid: string
in path

Insight OID.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full insight record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated insight record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this insight.

404 Not Found

Not Found — insight does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Remove a custom-field definition from an insight view by ID.

DELETE /insight/remove-field/id/{ownerType}/{ownerId}/{insightId}

Removes the named custom field from the insight view.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns 204 No Content, also when the field does not exist. A missing name query parameter returns 400.

ownerType: string project, organization, folder, smart-folder
in path

Owner type of the insight. Required here: it is not assumed to be project.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

name: string
in query

Name of the field to remove. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

204 No Content

No Content — field removed (or already absent).

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

Remove a custom-field definition from an insight view.

DELETE /insight/remove-field/{oid}

Removes the named custom field from the insight view.

Requires admin rights on the insight's owner (its project, organization, folder or smart folder) and an app with the Manage profiles permission; otherwise 403. External-team members always get 403.

Returns 204 No Content, also when the field does not exist. A missing name query parameter returns 400.

oid: string
in path

Insight OID.

name: string
in query

Name of the field to remove. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

204 No Content

No Content — field removed (or already absent).

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — caller is not an admin of the insight's owner, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

Delete an insight view by ID.

DELETE /insight/id/{ownerType}/{ownerId}/{insightId}

Removes the insight view. Restore it with PUT /insight/undo-remove/id/{ownerType}/{ownerId}/{insightId} (or /insight/undo-remove/{oid}).

Returns 204 No Content, also when the insight does not exist.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed; e.g., /id/my_project/insight1 is equivalent to /id/project/my_project/insight1.

ownerId: string
in path

Owner ID.

insightId: string
in path

Insight ID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this insight.

Response Content-Types: application/json

Delete an insight view by OID.

DELETE /insight/{oid}

Removes the insight view. Restore it with PUT /insight/undo-remove/id/{ownerType}/{ownerId}/{insightId} (or /insight/undo-remove/{oid}).

Returns 204 No Content, also when the insight does not exist.

oid: string
in path

Insight OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this insight.

Response Content-Types: application/json

notification

Send a notification to the user who authorized this app, or to their colleagues. Typically used to surface errors, alerts, or events worth flagging in Quire's notification panel.

Send a notification.

POST /notification

Sends a notification to the authorizing user (default) or to a list of recipients — the authorizing user and/or their colleagues — specified via recipients.

Eligible recipients are the authorizing user plus the colleagues this app can see — the same set returned by GET /user/list: when the user granted the app access to contacts, all colleagues are visible; otherwise only colleagues who also authorized this app.

An entry that does not exist or is not visible is rejected with 404 Not Found. The response is identical for every such case so the endpoint cannot be used to probe user existence or colleague relationships.

The app needs the Manage notifications permission, granted when the user authorized it; otherwise 403.

Rate-limit cost: one unit per 10 recipients, rounded up (at least 1), counted from the resolved list — so ["*"] costs one unit per 10 users visible to the app. It is charged only once the recipients resolve, so a call rejected with 404 costs nothing. It is counted against the organization of the user's best plan (a trial doesn't count); a user in no organization has a bucket of their own, at the Free plan's limits.

Returns 204 No Content.

url: string

(Optional) URL associated with the message. When provided, the client may render the message as a hyperlink.

A javascript: URL is rejected with 400. Without a scheme, such as example.com/sync, https:// is assumed; a path starting with / points into Quire.

recipients: string[]

(Optional) Recipients of the notification (OID, ID, or email of a user). Omit or send an empty list to notify only the authorizing user (default).

Each entry must be the authorizing user or a colleague visible to this app — exactly the set returned by GET /user/list. Entries that do not exist or are not visible are rejected with 404 Not Found; the response is identical regardless of the reason, so this endpoint cannot be used to probe whether a user exists.

Special value:

  • ["*"] — broadcast to every user visible to this app (same set as GET /user/list, including the authorizing user). * must be the sole entry; mixing it with other entries returns 400 Bad Request.

Rate-limit cost: one unit per 10 recipients, rounded up (at least 1), counted after * is expanded. A call made once the caller's per-minute or per-hour API budget is used up is rejected with 429 Too Many Requests and no notification is sent.

message: string

Notification message. Required; an empty one is rejected with 400.

Request Example
{
  "url": "https://superheros.com/sync",
  "recipients": "[\"bob@example.com\"]",
  "message": "Unable to synchronize"
}
204 No Content

No Content — notification accepted and queued for delivery.

400 Bad Request

Bad Request — message is missing or empty, url is a javascript: URL, recipients is not a list, or * was combined with other entries.

403 Forbidden

Forbidden — the app wasn't granted the Manage notifications permission.

404 Not Found

Not Found — one or more entries in recipients do not exist or are not visible to this app.

429 Too Many Requests

Too Many Requests — the caller's per-minute or per-hour API budget is used up. No notification is sent.

Response Content-Types: application/json

organization

An organization is a group of projects where members collaborate.

Get an organization by ID.

GET /organization/id/{id}

Returns the complete organization record for the given ID.

id: string
in path

Organization ID.

OK — organization record with plan info.

403 Forbidden

Forbidden — the user can't access the organization, or didn't authorize it for this app.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get an organization by OID.

GET /organization/{oid}

Returns the complete organization record for the given OID.

oid: string
in path

Organization OID.

OK — organization record with plan info.

403 Forbidden

Forbidden — the user can't access the organization, or didn't authorize it for this app.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get all organizations.

GET /organization/list

Returns organization records that the current user can authorize for this application, or already has authorized.

200 OK

OK — list of organizations (may be empty).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/c/my_organization",
    "email": "info@company.com",
    "nameText": "My Organization",
    "nameHtml": "My Organization",
    "name": "My Organization",
    "id": "my_organization",
    "website": "https://coolwebsites.com",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "followers": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Update an organization by ID.

PUT /organization/id/{id}

Updates an existing organization and returns the complete updated record. Omitted body fields are left unchanged.

Who may change what: name and description need an admin of the organization, and an app with the Manage profiles permission. followers, addFollowers and removeFollowers need edit access to the organization itself (being a member of one of its projects isn't enough), and an app with the Manage tasks permission — even for only "me": unlike a project, an organization can't be followed with read access. A body mixing them needs the rights of each; otherwise 403.

id: string
in path

Organization ID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full organization record, or compact for just {"oid": …, "id": …}. Any other value returns 400 Bad Request.

description: string

(Optional) New description for this organization (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Needs an admin of the organization.

addFollowers: string[]

(Optional) Followers to add to this organization (OID, ID, or email). Special values:

  • "me": the current user follows the organization
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

removeFollowers: string[]

(Optional) Followers to remove from this organization (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

followers: string[]

(Optional) Followers to replace the current followers of this organization (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

name: string

(Optional) New display name for this organization (Markdown supported). Needs an admin of the organization.

Request Example
{
  "description": "**Great** organization to start with.",
  "addFollowers": [
    "string"
  ],
  "removeFollowers": [
    "string"
  ],
  "followers": [
    "string"
  ],
  "name": "My Organization"
}
200 OK

OK — updated organization record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user lacks the role, or the app the permission, a given field needs: an admin and Manage profiles for name and description; edit access and Manage tasks for the followers.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update an organization by OID.

PUT /organization/{oid}

Updates an existing organization and returns the complete updated record. Omitted body fields are left unchanged.

Who may change what: name and description need an admin of the organization, and an app with the Manage profiles permission. followers, addFollowers and removeFollowers need edit access to the organization itself (being a member of one of its projects isn't enough), and an app with the Manage tasks permission — even for only "me": unlike a project, an organization can't be followed with read access. A body mixing them needs the rights of each; otherwise 403.

oid: string
in path

Organization OID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full organization record, or compact for just {"oid": …, "id": …}. Any other value returns 400 Bad Request.

description: string

(Optional) New description for this organization (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Needs an admin of the organization.

addFollowers: string[]

(Optional) Followers to add to this organization (OID, ID, or email). Special values:

  • "me": the current user follows the organization
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

removeFollowers: string[]

(Optional) Followers to remove from this organization (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

followers: string[]

(Optional) Followers to replace the current followers of this organization (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

name: string

(Optional) New display name for this organization (Markdown supported). Needs an admin of the organization.

Request Example
{
  "description": "**Great** organization to start with.",
  "addFollowers": [
    "string"
  ],
  "removeFollowers": [
    "string"
  ],
  "followers": [
    "string"
  ],
  "name": "My Organization"
}
200 OK

OK — updated organization record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user lacks the role, or the app the permission, a given field needs: an admin and Manage profiles for name and description; edit access and Manage tasks for the followers.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

partner

An external team (aka a partner) is a group of users who can access only the tasks assigned to that team.

Get an external team by OID.

GET /partner/{oid}

Returns the full external team record for the given OID.

oid: string
in path

External team OID.

200 OK

OK — external team record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — external team does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "UI design team",
  "color": "35",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List external teams by project ID.

GET /partner/list/id/{projectId}

Returns all external teams in the specified project (by project ID).

projectId: string
in path

Project ID.

200 OK

OK — list of external teams (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "name": "UI design team",
    "color": "35",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "project": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List external teams by project OID.

GET /partner/list/{projectOid}

Returns all external teams in the specified project (by project OID).

projectOid: string
in path

Project OID.

200 OK

OK — list of external teams (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "name": "UI design team",
    "color": "35",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "project": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

project

A project represents a prioritized list of tasks in Quire. It belongs to a single organization and is accessible to a subset of users in that organization, depending on its permissions.

Add an approval category to a project by ID.

POST /project/add-appv-cat/id/{id}

Adds an approval category to the project and returns it. A project always has the default category (id ""); add more to give each its own claimers and approvers.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Example:

{
  "id": "legal",
  "name": "Legal review",
  "approvers": ["iDsPd.QP_qM.hN.Trymukn8b"]
}

claimers and approvers are lists of user OIDs; omit them or pass null for anyone, [] for the project's admins only.

An id already in use in the project returns 409; a plan without multiple approval categories, 402.

id: string
in path

Project ID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the category, or compact for just {"id": …}. Any other value returns 400 Bad Request.

claimers: string[]

(Optional) Users allowed to request approval in this category.

  • Omit or null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
approvers: string[]

(Optional) Users allowed to approve, reject, or request changes in this category.

  • Omit or null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
name: string

Display name.

id: string

Category identifier (URL-safe). Must be unique within the project. The identifier "" is reserved for the implicit default category.

Request Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review",
  "id": "legal"
}
200 OK

OK — created approval category.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — the plan doesn't include multiple approval categories.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a category with this id already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Legal Review",
  "id": "legal",
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "claimerRefs": [
    {
      "id": "my_id",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "approverRefs": [
    "#/definitions/SimpleEntityWithId"
  ],
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2026-04-24T10:00:00.000Z"
}

Add an approval category to a project.

POST /project/add-appv-cat/{oid}

Adds an approval category to the project and returns it. A project always has the default category (id ""); add more to give each its own claimers and approvers.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Example:

{
  "id": "legal",
  "name": "Legal review",
  "approvers": ["iDsPd.QP_qM.hN.Trymukn8b"]
}

claimers and approvers are lists of user OIDs; omit them or pass null for anyone, [] for the project's admins only.

An id already in use in the project returns 409; a plan without multiple approval categories, 402.

oid: string
in path

Project OID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the category, or compact for just {"id": …}. Any other value returns 400 Bad Request.

claimers: string[]

(Optional) Users allowed to request approval in this category.

  • Omit or null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
approvers: string[]

(Optional) Users allowed to approve, reject, or request changes in this category.

  • Omit or null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
name: string

Display name.

id: string

Category identifier (URL-safe). Must be unique within the project. The identifier "" is reserved for the implicit default category.

Request Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review",
  "id": "legal"
}
200 OK

OK — created approval category.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — the plan doesn't include multiple approval categories.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a category with this id already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Legal Review",
  "id": "legal",
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "claimerRefs": [
    {
      "id": "my_id",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "approverRefs": [
    "#/definitions/SimpleEntityWithId"
  ],
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2026-04-24T10:00:00.000Z"
}

Add a custom-field definition to a project by ID.

POST /project/add-field/id/{id}

Adds a custom-field definition to the project and returns it as in Project.fields, plus its name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A project field's type is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file (lookup is for insights only). A key that doesn't apply to the type, such as options on a number field, returns 400.

Example — a single-select field with three options; each option is an object, not a plain string:

{
  "name": "Stage",
  "type": "select",
  "options": [
    {"name": "Todo"},
    {"name": "Review", "color": "13"},
    {"name": "Done", "color": "42"}
  ]
}

A name already in use returns 409; a field over the plan's custom-field limit returns 402.

id: string
in path

Project ID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(Optional, select only) Options, each an object with name and an optional color — not a plain string. Example: [{"name": "High", "color": "13"}, {"name": "Low"}].

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date, number, money, duration, lookup, and formula fields whose resultType resolves to one of those.

name: string

Unique name for this field. Must be a non-empty string of at most 1,280 characters, and must not contain }, ", or \.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "name": "Priority",
  "type": "number"
}

OK — created custom-field definition.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — plan's custom-field limit is reached (code 469).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a field with this name already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Add a custom-field definition to a project.

POST /project/add-field/{oid}

Adds a custom-field definition to the project and returns it as in Project.fields, plus its name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A project field's type is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file (lookup is for insights only). A key that doesn't apply to the type, such as options on a number field, returns 400.

Example — a single-select field with three options; each option is an object, not a plain string:

{
  "name": "Stage",
  "type": "select",
  "options": [
    {"name": "Todo"},
    {"name": "Review", "color": "13"},
    {"name": "Done", "color": "42"}
  ]
}

A name already in use returns 409; a field over the plan's custom-field limit returns 402.

oid: string
in path

Project OID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(Optional, select only) Options, each an object with name and an optional color — not a plain string. Example: [{"name": "High", "color": "13"}, {"name": "Low"}].

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date, number, money, duration, lookup, and formula fields whose resultType resolves to one of those.

name: string

Unique name for this field. Must be a non-empty string of at most 1,280 characters, and must not contain }, ", or \.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "name": "Priority",
  "type": "number"
}

OK — created custom-field definition.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — plan's custom-field limit is reached (code 469).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a field with this name already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Export a project to CSV by ID.

GET /project/export-csv/id/{id}

Returns a CSV string containing the project, tasks, and related data. Columns are separated by ,, or by ; if the user's locale uses a decimal comma (e.g. de, fr).

Available on the Professional plan and above; on a lower plan it returns 402 (code 469). Guests, and the visitors of a public project, can't export it (403).

Rate-limit cost: 5 + max(1, ceil(tasks / 100)) units, where tasks counts only the tasks matching ?status=, not the project total — e.g. 6 for 100 tasks, 15 for 1,000. It applies only to an export that runs: one rejected with 402 for the plan costs 1 unit, like any call. See also Rate Limits.

id: string
in path

Project ID.

status: string
in query

Task status filter. Use active for active tasks, completed for completed tasks, or all for all tasks. Default: all.

merge: boolean
in query

Whether to merge multiple values of the same header into one column (e.g., all tags in a single column). Default: false.

comments: boolean
in query

Whether to include task comments, oldest first. Each is the author's name and when it was posted, in the user's locale and time zone, followed by a colon, a line feed and the comment, e.g. Tom Yeh, Nov 3, 2026 14:30:\nLooks good. With merge, a task's comments are in one column, separated by a blank line; otherwise, each comment is in a column of its own. Comments without text (e.g., attachments only) are skipped. Default: false.

200 OK

OK — CSV export of project.

402 Payment Required

Payment Required — the plan doesn't include export (code 469).

403 Forbidden

Forbidden — the user can't access the project, or is a guest.

404 Not Found

Not Found — project does not exist.

Response Content-Types: text/csv
Response Example (200 OK)
"ID",Name,Status,Started,Completed,Priority,Start,Due,Assignee,Tag,Created,Created by,Description
#6,Task A,In Progress,"Mar 8, 2022",,Medium,,"Mar 8, 2022",,,"Mar 7, 2022",John,
"#6, #8",Task A1,To-Do,"Jan 24, 2022",,Urgent,,,,,"Mar 7, 2022",John,
#7,Task B,In Progress,"Jan 24, 2022",,Urgent,,"Mar 4, 2022",,,"Mar 7, 2022",John,
"#7, #9",Task B1,In Progress,"Jan 24, 2022",,Medium,,,,,"Mar 7, 2022",John,
"#7, #4",Task B2,In Progress,"Mar 2, 2022",,Medium,,"Mar 8, 2022",,,"Mar 2, 2022",John,

Export a project to CSV by OID.

GET /project/export-csv/{oid}

Returns a CSV string containing the project, tasks, and related data. Columns are separated by ,, or by ; if the user's locale uses a decimal comma (e.g. de, fr).

Available on the Professional plan and above; on a lower plan it returns 402 (code 469). Guests, and the visitors of a public project, can't export it (403).

Rate-limit cost: 5 + max(1, ceil(tasks / 100)) units, where tasks counts only the tasks matching ?status=, not the project total — e.g. 6 for 100 tasks, 15 for 1,000. It applies only to an export that runs: one rejected with 402 for the plan costs 1 unit, like any call. See also Rate Limits.

oid: string
in path

Project OID.

status: string
in query

Task status filter. Use active for active tasks, completed for completed tasks, or all for all tasks. Default: all.

merge: boolean
in query

Whether to merge multiple values of the same header into one column (e.g., all tags in a single column). Default: false.

comments: boolean
in query

Whether to include task comments, oldest first. Each is the author's name and when it was posted, in the user's locale and time zone, followed by a colon, a line feed and the comment, e.g. Tom Yeh, Nov 3, 2026 14:30:\nLooks good. With merge, a task's comments are in one column, separated by a blank line; otherwise, each comment is in a column of its own. Comments without text (e.g., attachments only) are skipped. Default: false.

200 OK

OK — CSV export of project.

402 Payment Required

Payment Required — the plan doesn't include export (code 469).

403 Forbidden

Forbidden — the user can't access the project, or is a guest.

404 Not Found

Not Found — project does not exist.

Response Content-Types: text/csv
Response Example (200 OK)
"ID",Name,Status,Started,Completed,Priority,Start,Due,Assignee,Tag,Created,Created by,Description
#6,Task A,In Progress,"Mar 8, 2022",,Medium,,"Mar 8, 2022",,,"Mar 7, 2022",John,
"#6, #8",Task A1,To-Do,"Jan 24, 2022",,Urgent,,,,,"Mar 7, 2022",John,
#7,Task B,In Progress,"Jan 24, 2022",,Urgent,,"Mar 4, 2022",,,"Mar 7, 2022",John,
"#7, #9",Task B1,In Progress,"Jan 24, 2022",,Medium,,,,,"Mar 7, 2022",John,
"#7, #4",Task B2,In Progress,"Mar 2, 2022",,Medium,,"Mar 8, 2022",,,"Mar 2, 2022",John,

Export a project to JSON by ID.

GET /project/export-json/id/{id}

Returns a JSON map containing the project, its tasks, and related data: users, tags, external teams, sublists, documents, chats, insights, dashboards and reminders.

Available on the Professional plan and above; on a lower plan it returns 402 (code 469). Guests, and the visitors of a public project, can't export it (403).

Rate-limit cost: 5 + max(1, ceil(tasks / 100)) units, where tasks counts only the tasks matching ?status=, not the project total — e.g. 6 for 100 tasks, 15 for 1,000. It applies only to an export that runs: one rejected with 402 for the plan costs 1 unit, like any call. See also Rate Limits.

id: string
in path

Project ID.

status: string
in query

Task status filter. Use active for active tasks, completed for completed tasks, or all for all tasks. Default: all.

OK — JSON export of project.

402 Payment Required

Payment Required — the plan doesn't include export (code 469).

403 Forbidden

Forbidden — the user can't access the project, or is a guest.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "version": "9.0.0",
  "tasks": [
    "object"
  ],
  "tags": [
    "object"
  ],
  "users": [
    "object"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partners": [
    "object"
  ],
  "reminders": [
    "object"
  ],
  "sublists": [
    "object"
  ],
  "docs": [
    "object"
  ],
  "chats": [
    "object"
  ],
  "insights": [
    "object"
  ],
  "dashboards": [
    "object"
  ],
  "name": "My Project",
  "id": "My_Project",
  "members": [
    "string"
  ]
}

Export a project to JSON by OID.

GET /project/export-json/{oid}

Returns a JSON map containing the project, its tasks, and related data: users, tags, external teams, sublists, documents, chats, insights, dashboards and reminders.

Available on the Professional plan and above; on a lower plan it returns 402 (code 469). Guests, and the visitors of a public project, can't export it (403).

Rate-limit cost: 5 + max(1, ceil(tasks / 100)) units, where tasks counts only the tasks matching ?status=, not the project total — e.g. 6 for 100 tasks, 15 for 1,000. It applies only to an export that runs: one rejected with 402 for the plan costs 1 unit, like any call. See also Rate Limits.

oid: string
in path

Project OID.

status: string
in query

Task status filter. Use active for active tasks, completed for completed tasks, or all for all tasks. Default: all.

OK — JSON export of project.

402 Payment Required

Payment Required — the plan doesn't include export (code 469).

403 Forbidden

Forbidden — the user can't access the project, or is a guest.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "version": "9.0.0",
  "tasks": [
    "object"
  ],
  "tags": [
    "object"
  ],
  "users": [
    "object"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partners": [
    "object"
  ],
  "reminders": [
    "object"
  ],
  "sublists": [
    "object"
  ],
  "docs": [
    "object"
  ],
  "chats": [
    "object"
  ],
  "insights": [
    "object"
  ],
  "dashboards": [
    "object"
  ],
  "name": "My Project",
  "id": "My_Project",
  "members": [
    "string"
  ]
}

Get a project by ID.

GET /project/id/{id}

Returns the complete project record for the given ID. Use - for the user's My Tasks (personal tasks, not in any project).

id: string
in path

Project ID, or - for My Tasks.

OK — project record.

403 Forbidden

Forbidden — the user can't access the project, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a project by OID.

GET /project/{oid}

Returns the complete project record for the given OID. Use - for the user's My Tasks (personal tasks, not in any project).

oid: string
in path

Project OID, or - for My Tasks.

OK — project record.

403 Forbidden

Forbidden — the user can't access the project, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get all authorized projects.

GET /project/list

Returns projects that the current user has authorized for this application. If the user authorized My Tasks (personal tasks, not in any project) too, it is in the list as well.

archived: boolean
in query

Whether to include archived projects. By default, archived projects are excluded. If the parameter is present without a value, true is assumed.

add-task: boolean
in query

Whether to return only projects to which you can add tasks. Default: false. If the parameter is present without a value, true is assumed.

200 OK

OK — list of authorized projects (may be empty).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "activeCount": 20,
    "taskCount": 30,
    "url": "https://quire.io/w/my_project",
    "organization": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "nameText": "My Project",
    "nameHtml": "My Project",
    "rootCount": 5,
    "name": "My Project",
    "id": "my_project",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "archivedAt": "2018-12-22T02:06:58.158Z",
    "start": "2024-01-02",
    "due": "2024-05-25",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "publicAt": "2018-12-22T02:06:58.158Z",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "approvalCategories": [
      {
        "name": "Legal Review",
        "id": "legal",
        "claimers": [
          "string"
        ],
        "approvers": [
          "string"
        ],
        "claimerRefs": [
          {
            "id": "my_id",
            "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
          }
        ],
        "approverRefs": [
          "#/definitions/SimpleEntityWithId"
        ],
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2026-04-24T10:00:00.000Z"
      }
    ],
    "fields": "object",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Get authorized projects by organization ID.

GET /project/list/id/{organizationId}

Returns projects in the specified organization (by ID) that the current user has authorized.

organizationId: string
in path

Organization ID.

archived: boolean
in query

Whether to include archived projects. By default, archived projects are excluded. If the parameter is present without a value, true is assumed.

add-task: boolean
in query

Whether to return only projects to which you can add tasks. Default: false. If the parameter is present without a value, true is assumed.

200 OK

OK — list of authorized projects (may be empty).

403 Forbidden

Forbidden — the user can't access the organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "activeCount": 20,
    "taskCount": 30,
    "url": "https://quire.io/w/my_project",
    "organization": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "nameText": "My Project",
    "nameHtml": "My Project",
    "rootCount": 5,
    "name": "My Project",
    "id": "my_project",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "archivedAt": "2018-12-22T02:06:58.158Z",
    "start": "2024-01-02",
    "due": "2024-05-25",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "publicAt": "2018-12-22T02:06:58.158Z",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "approvalCategories": [
      {
        "name": "Legal Review",
        "id": "legal",
        "claimers": [
          "string"
        ],
        "approvers": [
          "string"
        ],
        "claimerRefs": [
          {
            "id": "my_id",
            "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
          }
        ],
        "approverRefs": [
          "#/definitions/SimpleEntityWithId"
        ],
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2026-04-24T10:00:00.000Z"
      }
    ],
    "fields": "object",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Get authorized projects by organization OID.

GET /project/list/{organizationOid}

Returns projects in the specified organization (by OID) that the current user has authorized.

organizationOid: string
in path

Organization OID.

archived: boolean
in query

Whether to include archived projects. By default, archived projects are excluded. If the parameter is present without a value, true is assumed.

add-task: boolean
in query

Whether to return only projects to which you can add tasks. Default: false. If the parameter is present without a value, true is assumed.

200 OK

OK — list of authorized projects (may be empty).

403 Forbidden

Forbidden — the user can't access the organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "activeCount": 20,
    "taskCount": 30,
    "url": "https://quire.io/w/my_project",
    "organization": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "nameText": "My Project",
    "nameHtml": "My Project",
    "rootCount": 5,
    "name": "My Project",
    "id": "my_project",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "archivedAt": "2018-12-22T02:06:58.158Z",
    "start": "2024-01-02",
    "due": "2024-05-25",
    "editedAt": "2018-12-22T02:06:58.158Z",
    "publicAt": "2018-12-22T02:06:58.158Z",
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "followers": [
      "#/definitions/SimpleIdentity"
    ],
    "approvalCategories": [
      {
        "name": "Legal Review",
        "id": "legal",
        "claimers": [
          "string"
        ],
        "approvers": [
          "string"
        ],
        "claimerRefs": [
          {
            "id": "my_id",
            "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
          }
        ],
        "approverRefs": [
          "#/definitions/SimpleEntityWithId"
        ],
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2026-04-24T10:00:00.000Z"
      }
    ],
    "fields": "object",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Reorder a custom-field definition on a project by ID.

PUT /project/move-field/id/{id}

Moves a custom field to just before the before field, or to the end if before is omitted, and returns it as in Project.fields, plus its name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A missing field, or a missing before field, returns 404.

id: string
in path

Project ID.

name: string
in query

Name of the field to move. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

before: string
in query

(Optional) Name of the field to insert before. If omitted, the field is moved to the end. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

OK — moved custom-field definition.

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project, field or before field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Reorder a custom-field definition on a project.

PUT /project/move-field/{oid}

Moves a custom field to just before the before field, or to the end if before is omitted, and returns it as in Project.fields, plus its name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A missing field, or a missing before field, returns 404.

oid: string
in path

Project OID.

name: string
in query

Name of the field to move. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

before: string
in query

(Optional) Name of the field to insert before. If omitted, the field is moved to the end. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

OK — moved custom-field definition.

400 Bad Request

Bad Request — name missing.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project, field or before field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Rename a custom-field definition on a project by ID.

PUT /project/rename-field/id/{id}

Renames a custom field and returns it as in Project.fields, plus its name (the new name). The definition is kept, and task values move to the new name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A missing field returns 404; a new-name already in use, 409; an invalid new-name, 400 — it must be non-empty, without }, " or \, and at most 1,280 characters.

id: string
in path

Project ID.

name: string
in query

Current field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

new-name: string
in query

New field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

OK — renamed custom-field definition.

400 Bad Request

Bad Request — name missing, or new-name missing or invalid.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project or field does not exist.

409 Conflict

Conflict — new-name is already in use.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Rename a custom-field definition on a project.

PUT /project/rename-field/{oid}

Renames a custom field and returns it as in Project.fields, plus its name (the new name). The definition is kept, and task values move to the new name.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

A missing field returns 404; a new-name already in use, 409; an invalid new-name, 400 — it must be non-empty, without }, " or \, and at most 1,280 characters.

oid: string
in path

Project OID.

name: string
in query

Current field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

new-name: string
in query

New field name. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

OK — renamed custom-field definition.

400 Bad Request

Bad Request — name missing, or new-name missing or invalid.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project or field does not exist.

409 Conflict

Conflict — new-name is already in use.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Update an approval category on a project by ID.

PUT /project/update-appv-cat/id/{id}/{catId}

Partial update: any of name, claimers, or approvers may be supplied; omitted keys preserve their current values. At least one key must be present, or it returns 400. claimers and approvers are lists of user OIDs; omit them or pass null for anyone, [] for the project's admins only.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Response body is the updated category, or an empty object if the category no longer exists (e.g. removed concurrently). A plan without approvals returns 402.

id: string
in path

Project ID.

catId: string
in path

Category id.

return: string full, compact
in query

(Optional) Response shape: full (default) for the category, or compact for just {"id": …}. Any other value returns 400 Bad Request.

claimers: string[]

(Optional) New claimers list — users allowed to request approval in this category.

  • null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
approvers: string[]

(Optional) New approvers list — users allowed to approve, reject, or request changes in this category.

  • null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
name: string

(Optional) New display name.

Request Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review"
}
200 OK

OK — updated approval category.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — the plan doesn't include approvals.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Legal Review",
  "id": "legal",
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "claimerRefs": [
    {
      "id": "my_id",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "approverRefs": [
    "#/definitions/SimpleEntityWithId"
  ],
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2026-04-24T10:00:00.000Z"
}

Update an approval category on a project.

PUT /project/update-appv-cat/{oid}/{catId}

Partial update: any of name, claimers, or approvers may be supplied; omitted keys preserve their current values. At least one key must be present, or it returns 400. claimers and approvers are lists of user OIDs; omit them or pass null for anyone, [] for the project's admins only.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Response body is the updated category, or an empty object if the category no longer exists (e.g. removed concurrently). A plan without approvals returns 402.

oid: string
in path

Project OID.

catId: string
in path

Category id.

return: string full, compact
in query

(Optional) Response shape: full (default) for the category, or compact for just {"id": …}. Any other value returns 400 Bad Request.

claimers: string[]

(Optional) New claimers list — users allowed to request approval in this category.

  • null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
approvers: string[]

(Optional) New approvers list — users allowed to approve, reject, or request changes in this category.

  • null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
name: string

(Optional) New display name.

Request Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review"
}
200 OK

OK — updated approval category.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — the plan doesn't include approvals.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Legal Review",
  "id": "legal",
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "claimerRefs": [
    {
      "id": "my_id",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "approverRefs": [
    "#/definitions/SimpleEntityWithId"
  ],
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2026-04-24T10:00:00.000Z"
}

Update a custom-field definition on a project by ID.

PUT /project/update-field/id/{id}

Updates the named custom field's definition and returns it as in Project.fields, plus its name. type is immutable: if supplied, it must match the current type. Omitted keys, flags such as hidden and locked included, keep their current values. A key that doesn't apply to the field's type returns 400. options and conditionFormat replace the whole list, and [] removes every entry.

To rename a select option, give its current name in from; tasks set to it get the new name. Example — rename High to Critical and keep Low:

{"options": [{"name": "Low"}, {"name": "Critical", "from": "High"}]}

Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches; a new option gets one assigned. A from that names no current option, two entries matching the same option (by name or from), a duplicate name, or a name over 1,280 characters returns 400.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Example — hide the field and lock its values: {"hidden": true, "locked": true}.

To rename a field, use PUT /project/rename-field/id/{projectId}?name={fieldName}&new-name={newName}; to reorder, PUT /project/move-field/id/{projectId}?name={fieldName}.

A missing field returns 404.

id: string
in path

Project ID.

name: string
in query

Name of the field to update. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. Pass $ to reset a money field to its default.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: UpdateFieldOption

(Optional, select only) Replacement option list, each an object with name, an optional color, and an optional from. It replaces the entire set; [] removes every option. To rename an option, give its current name in from, e.g. {"name": "Critical", "from": "High"}; tasks set to it get the new name. Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches (by from, else by name).

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity. Replaces the entire map.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys.

conditionFormat: FieldConditionFormat

(Optional) Replacement conditional-format rules. It replaces the entire list; [] removes every rule.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

(Optional) Field type. Immutable on update — if supplied, must match the existing field's type. Usually omitted; include only to verify the stored type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "from": "High",
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

OK — updated custom-field definition.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project or field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Update a custom-field definition on a project.

PUT /project/update-field/{oid}

Updates the named custom field's definition and returns it as in Project.fields, plus its name. type is immutable: if supplied, it must match the current type. Omitted keys, flags such as hidden and locked included, keep their current values. A key that doesn't apply to the field's type returns 400. options and conditionFormat replace the whole list, and [] removes every entry.

To rename a select option, give its current name in from; tasks set to it get the new name. Example — rename High to Critical and keep Low:

{"options": [{"name": "Low"}, {"name": "Critical", "from": "High"}]}

Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches; a new option gets one assigned. A from that names no current option, two entries matching the same option (by name or from), a duplicate name, or a name over 1,280 characters returns 400.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Example — hide the field and lock its values: {"hidden": true, "locked": true}.

To rename a field, use PUT /project/rename-field/id/{projectId}?name={fieldName}&new-name={newName}; to reorder, PUT /project/move-field/id/{projectId}?name={fieldName}.

A missing field returns 404.

oid: string
in path

Project OID.

name: string
in query

Name of the field to update. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

return: string full, compact
in query

(Optional) Response shape: full (default) for the field definition, or compact for just {"name": …}. Any other value returns 400 Bad Request.

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. Pass $ to reset a money field to its default.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: UpdateFieldOption

(Optional, select only) Replacement option list, each an object with name, an optional color, and an optional from. It replaces the entire set; [] removes every option. To rename an option, give its current name in from, e.g. {"name": "Critical", "from": "High"}; tasks set to it get the new name. Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches (by from, else by name).

lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity. Replaces the entire map.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys.

conditionFormat: FieldConditionFormat

(Optional) Replacement conditional-format rules. It replaces the entire list; [] removes every rule.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

(Optional) Field type. Immutable on update — if supplied, must match the existing field's type. Usually omitted; include only to verify the stored type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Request Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "from": "High",
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

OK — updated custom-field definition.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

404 Not Found

Not Found — project or field does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

Update a project by ID.

PUT /project/id/{id}

Updates an existing project and returns the complete updated record.

To archive or unarchive, set archived: true or archived: false in the body.

Who may change what: name, description, archived, public, start and due need a project admin, and an app with the Manage profiles permission. Followers need edit access to the project (not as an external team member), and an app with the Manage tasks permission, except for following or unfollowing yourself. With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. A body mixing them needs the rights of each; otherwise 403.

id: string
in path

Project ID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"oid": …, "id": …}. Any other value returns 400 Bad Request.

public: boolean

(Optional) Public toggle. Specify true to make this project public; specify false to make it private. Making it public needs a plan with public projects; otherwise 402 (code 469).

description: string

(Optional) New description for this project (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

archived: boolean

(Optional) Archive toggle. Specify true to archive this project; specify false to unarchive.

addFollowers: string[]

(Optional) Followers to add to this project (OID, ID, or email). Special values:

  • "me": the current user follows the project
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

removeFollowers: string[]

(Optional) Followers to remove from this project (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

start: string

(Optional) Target start date for this project: a date only, e.g. 2024-01-02; a value with a time of day returns 400. null clears it. Needs a project admin.

due: string

(Optional) Target due date for this project: a date only, e.g. 2024-05-25; a value with a time of day returns 400. null clears it. Needs a project admin.

followers: string[]

(Optional) Followers to replace the current followers of this project (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

name: string

(Optional) New display name for this project (Markdown supported).

Request Example
{
  "public": true,
  "description": "**Great** project to start with.",
  "archived": true,
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "start": "2024-01-02",
  "due": "2024-05-25",
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "name": "My Project"
}
200 OK

OK — updated project record.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — public: true on a plan without public projects (code 469).

403 Forbidden

Forbidden — the user lacks the role, or the app the permission, a given field needs: an admin and Manage profiles for name, description, archived, public, start and due; edit access and Manage tasks for followers, or for adding or removing anyone else, even along with yourself.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a project by OID.

PUT /project/{oid}

Updates an existing project and returns the complete updated record.

To archive or unarchive, set archived: true or archived: false in the body.

Who may change what: name, description, archived, public, start and due need a project admin, and an app with the Manage profiles permission. Followers need edit access to the project (not as an external team member), and an app with the Manage tasks permission, except for following or unfollowing yourself. With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. A body mixing them needs the rights of each; otherwise 403.

oid: string
in path

Project OID.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"oid": …, "id": …}. Any other value returns 400 Bad Request.

public: boolean

(Optional) Public toggle. Specify true to make this project public; specify false to make it private. Making it public needs a plan with public projects; otherwise 402 (code 469).

description: string

(Optional) New description for this project (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

archived: boolean

(Optional) Archive toggle. Specify true to archive this project; specify false to unarchive.

addFollowers: string[]

(Optional) Followers to add to this project (OID, ID, or email). Special values:

  • "me": the current user follows the project
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

removeFollowers: string[]

(Optional) Followers to remove from this project (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

start: string

(Optional) Target start date for this project: a date only, e.g. 2024-01-02; a value with a time of day returns 400. null clears it. Needs a project admin.

due: string

(Optional) Target due date for this project: a date only, e.g. 2024-05-25; a value with a time of day returns 400. null clears it. Needs a project admin.

followers: string[]

(Optional) Followers to replace the current followers of this project (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

name: string

(Optional) New display name for this project (Markdown supported).

Request Example
{
  "public": true,
  "description": "**Great** project to start with.",
  "archived": true,
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "start": "2024-01-02",
  "due": "2024-05-25",
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "name": "My Project"
}
200 OK

OK — updated project record.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — public: true on a plan without public projects (code 469).

403 Forbidden

Forbidden — the user lacks the role, or the app the permission, a given field needs: an admin and Manage profiles for name, description, archived, public, start and due; edit access and Manage tasks for followers, or for adding or removing anyone else, even along with yourself.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Remove an approval category from a project by ID.

DELETE /project/remove-appv-cat/id/{id}/{catId}

Removes the category. Any task whose approval references this category has its approval cleared.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Returns 204 No Content, also when the category doesn't exist.

id: string
in path

Project ID.

catId: string
in path

Category id.

204 No Content

No Content — category removed (or already absent).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

Remove an approval category from a project.

DELETE /project/remove-appv-cat/{oid}/{catId}

Removes the category. Any task whose approval references this category has its approval cleared.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Returns 204 No Content, also when the category doesn't exist.

oid: string
in path

Project OID.

catId: string
in path

Category id.

204 No Content

No Content — category removed (or already absent).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

Remove a custom-field definition from a project by ID.

DELETE /project/remove-field/id/{id}

Removes the named custom field from the project, and its value from every task (for a file field, the files too). This can't be undone.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Returns 204 No Content, also when the field doesn't exist.

id: string
in path

Project ID.

name: string
in query

Name of the field to remove. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

204 No Content

No Content — field removed (or already absent).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

Remove a custom-field definition from a project.

DELETE /project/remove-field/{oid}

Removes the named custom field from the project, and its value from every task (for a file field, the files too). This can't be undone.

Requires a user who is an admin of the project, and an app authorized with the Manage profiles permission; otherwise 403.

Returns 204 No Content, also when the field doesn't exist.

oid: string
in path

Project OID.

name: string
in query

Name of the field to remove. Percent-encode it, e.g. Billable%20Amount for Billable Amount; a + in the name must be %2B, since + means a space in a query.

204 No Content

No Content — field removed (or already absent).

403 Forbidden

Forbidden — the user isn't an admin of the project, or the app lacks the Manage profiles permission.

Response Content-Types: application/json

rate-limit

Inspect the current API rate-limit usage for an organization.

Get rate-limit usage by organization ID.

GET /rate-limit/id/{id}

Returns the current per-hour and per-minute API usage for the organization with the given ID.

plan and the limits are those enforced. A trial doesn't change them: during one, they stay those of the plan before the trial.

For organizations in a paid master group, counters are shared across all organizations in the group.

This call is free: it never counts against the rate limit, so you can make it even while throttled.

id: string
in path

Organization ID.

200 OK

OK — current rate-limit counters.

403 Forbidden

Forbidden — caller can't access this organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "hour": {
    "limit": 1250,
    "remaining": 1208,
    "used": 42,
    "reset": 1774863600
  },
  "minute": "#/definitions/RateLimitBucket",
  "organization": "YxjapXXRCOYxoaiCT4tT3OQm",
  "plan": "Enterprise"
}

Get rate-limit usage by organization OID.

GET /rate-limit/{oid}

Returns the current per-hour and per-minute API usage for the organization with the given OID.

plan and the limits are those enforced. A trial doesn't change them: during one, they stay those of the plan before the trial.

For organizations in a paid master group, counters are shared across all organizations in the group.

This call is free: it never counts against the rate limit, so you can make it even while throttled.

oid: string
in path

Organization OID.

200 OK

OK — current rate-limit counters.

403 Forbidden

Forbidden — caller can't access this organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "hour": {
    "limit": 1250,
    "remaining": 1208,
    "used": 42,
    "reset": 1774863600
  },
  "minute": "#/definitions/RateLimitBucket",
  "organization": "YxjapXXRCOYxoaiCT4tT3OQm",
  "plan": "Enterprise"
}

reminder

A reminder notifies the people it names, either before a task's start or due date or at a time of its own.

Create a reminder by owner OID.

POST /reminder/{ownerType}/{ownerOid}

Creates a reminder on the given task, or under the given project, organization, folder or smart folder.

What a reminder on a task fires from depends on the task: one with a start or due date supplies the time — its due date, or its start date if it has no due date — so send leads alone. Sending when or recurrence then is rejected with 400, since they would be ignored. On a task with neither date, when is required. Without a task, when is required: the reminder has no other time to fire from.

A guest can't create one: a reminder takes write access, which a guest lacks, so 403.

Examples:

  • POST /reminder/task/{taskOid} with {"leads": [{"days": 1, "at": "09:00"}]} — on a task with a due date, notifies you at 9:00 the day before it is due.
  • POST /reminder/project/- with {"when": "2027-01-15T09:00:00.000Z", "name": "Pay the **bill**"} — notifies you at that time, as a personal reminder.
ownerType: string
in path

What the reminder belongs to: project, organization, folder, smart-folder, or task.

Always required; it doesn't default to project.

With task, the reminder is attached to that task and belongs to the task's project. A reminder cannot be moved to another task afterwards, and the task is chosen here rather than in the body — there is no task field to send.

ownerOid: string
in path

OID of what the reminder belongs to — a project, organization, folder, smart folder, or task, per ownerType.

Pass - with ownerType project for My Tasks, i.e. a personal reminder, visible to nobody else.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full reminder record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

when: string

When this reminder fires (UTC, ISO 8601). A plain instant — there is no all-day reminder, so a bare date is midnight UTC.

Required for a reminder that has no task, or whose task has neither a start nor a due date.

Rejected with 400 when the task already has a start or due date: the reminder then fires from the task's own schedule, and a when of its own would be ignored. Send leads alone in that case.

recurrence: Recurrence

(Optional) How this reminder repeats; when is the first occurrence.

Rejected with 400 on a reminder whose task has a start or due date — it then repeats with its task's schedule, so a rule of its own would be ignored.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Omit it for a single notification at the fire time, which is the default ([{"minutes": 0}]).

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

name: string

(Optional) Text to show instead of the default message. Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

partner: string

(Optional) OID of the external team to share this reminder with; it then reaches every member of the project and of that team.

Only a project's reminder can carry one, and it cannot be combined with a members list ([] included) — both are 400. Without a task, it must be one of the project's external teams (400 otherwise). On a reminder attached to a task, it must be the team the task is shared with — the task's partner, or the nearest parent task's if it has none — or be omitted; any other value, and any value for a task not shared with a team, is 400.

An external team member shares a reminder with every member only through their own team. With members null, they must set partner to one of their teams; on a reminder attached to a task, that is the task's team. Otherwise 400 says what to send, as it does for a team of the project that isn't theirs.

Sharing with a team is part of Shared reminders, which needs the Premium plan or above (402 otherwise). Settable only when creating the reminder.

members: string[]

(Optional) Users who can see this reminder, and the only ones it notifies. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field — only the authenticated user. This is the default, except with partner: then every member of the project and of that team.
  • Pass null — every member of the owner. An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins.
  • Pass a list — only those users.

Unlike a work's members, omitting the field does not mean every member: pass null explicitly for that.

Omitting it without partner, or naming only yourself (such as ["me"]), keeps the reminder yours; anything else shares it — the Shared reminders feature, which needs the Premium plan or above (402 otherwise).

Rejected with 400 when a listed user is not a member of the owner, when a non-empty list does not include the authenticated user, or when partner is also set. On a reminder attached to a task, every listed user must also be able to see the task (400 naming those who can't): a project member sees every task, but an external team member only the tasks shared with their team. A guest sees only the reminders naming them, and creates none (403: a reminder takes write access).

Settable only when creating the reminder. It cannot be changed afterwards, so recreate the reminder to change who can see it. A personal reminder (created under -) is always its owner's alone, so no one else can be named.

Request Example
{
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill**",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created reminder record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project, or, on a task, other than the team the task is shared with, or members naming a user who can't see the task.

402 Payment Required

Payment Required — reminders need a Professional plan or above, and Shared reminders (members other than yourself, or partner) need Premium or above.

403 Forbidden

Forbidden — caller lacks permission to create a reminder here (a guest included: a reminder takes write access).

404 Not Found

Not Found — the owner does not exist, the task is in the trash, or the caller can't see the task (an external team member can't see one that isn't shared with their team).

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create a reminder on a task, by ID.

POST /reminder/id/task/{projectId}/{taskId}

Creates a reminder on the given task. The reminder belongs to that task's project.

What a reminder on a task fires from depends on the task: one with a start or due date supplies the time — its due date, or its start date if it has no due date — so send leads alone. Sending when or recurrence then is rejected with 400, since they would be ignored. On a task with neither date, when is required.

A guest can't create one: a reminder takes write access, which a guest lacks, so 403.

Example: POST /reminder/id/task/my_project/42 with {"leads": [{"days": 1, "at": "09:00"}]} — on a task with a due date, notifies you at 9:00 the day before it is due.

projectId: string
in path

ID of the project the task belongs to.

taskId: integer
in path

ID of the task, an integer unique within its project.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full reminder record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

when: string

When this reminder fires (UTC, ISO 8601). A plain instant — there is no all-day reminder, so a bare date is midnight UTC.

Required for a reminder that has no task, or whose task has neither a start nor a due date.

Rejected with 400 when the task already has a start or due date: the reminder then fires from the task's own schedule, and a when of its own would be ignored. Send leads alone in that case.

recurrence: Recurrence

(Optional) How this reminder repeats; when is the first occurrence.

Rejected with 400 on a reminder whose task has a start or due date — it then repeats with its task's schedule, so a rule of its own would be ignored.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Omit it for a single notification at the fire time, which is the default ([{"minutes": 0}]).

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

name: string

(Optional) Text to show instead of the default message. Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

partner: string

(Optional) OID of the external team to share this reminder with; it then reaches every member of the project and of that team.

Only a project's reminder can carry one, and it cannot be combined with a members list ([] included) — both are 400. Without a task, it must be one of the project's external teams (400 otherwise). On a reminder attached to a task, it must be the team the task is shared with — the task's partner, or the nearest parent task's if it has none — or be omitted; any other value, and any value for a task not shared with a team, is 400.

An external team member shares a reminder with every member only through their own team. With members null, they must set partner to one of their teams; on a reminder attached to a task, that is the task's team. Otherwise 400 says what to send, as it does for a team of the project that isn't theirs.

Sharing with a team is part of Shared reminders, which needs the Premium plan or above (402 otherwise). Settable only when creating the reminder.

members: string[]

(Optional) Users who can see this reminder, and the only ones it notifies. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field — only the authenticated user. This is the default, except with partner: then every member of the project and of that team.
  • Pass null — every member of the owner. An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins.
  • Pass a list — only those users.

Unlike a work's members, omitting the field does not mean every member: pass null explicitly for that.

Omitting it without partner, or naming only yourself (such as ["me"]), keeps the reminder yours; anything else shares it — the Shared reminders feature, which needs the Premium plan or above (402 otherwise).

Rejected with 400 when a listed user is not a member of the owner, when a non-empty list does not include the authenticated user, or when partner is also set. On a reminder attached to a task, every listed user must also be able to see the task (400 naming those who can't): a project member sees every task, but an external team member only the tasks shared with their team. A guest sees only the reminders naming them, and creates none (403: a reminder takes write access).

Settable only when creating the reminder. It cannot be changed afterwards, so recreate the reminder to change who can see it. A personal reminder (created under -) is always its owner's alone, so no one else can be named.

Request Example
{
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill**",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created reminder record.

400 Bad Request

Bad Request — body validation failed, for example a partner other than the team the task is shared with, or members naming a user who can't see the task.

402 Payment Required

Payment Required — reminders need a Professional plan or above, and Shared reminders (members other than yourself, or partner) need Premium or above.

403 Forbidden

Forbidden — caller lacks permission to create a reminder here (a guest included: a reminder takes write access).

404 Not Found

Not Found — the task does not exist, is in the trash, or the caller can't see the task (an external team member can't see one that isn't shared with their team).

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create a reminder by owner ID.

POST /reminder/id/{ownerType}/{ownerId}

Creates a reminder under the given project, organization, folder or smart folder (by ID).

Without a task, when is required: the reminder has no other time to fire from.

For a reminder on a task, use POST /reminder/id/task/{projectId}/{taskId} — a task ID is unique only within its project, so it needs both.

A guest can't create one: a reminder takes write access, which a guest lacks, so 403.

Example: POST /reminder/id/project/my_project with {"when": "2027-01-15T09:00:00.000Z", "name": "Pay the **bill**"} — notifies you at that time.

ownerType: string
in path

What the reminder belongs to: project, organization, folder, or smart-folder. Always required.

ownerId: string
in path

ID of what the reminder belongs to. Pass - with ownerType project for My Tasks, i.e. a personal reminder, visible to nobody else.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full reminder record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

when: string

When this reminder fires (UTC, ISO 8601). A plain instant — there is no all-day reminder, so a bare date is midnight UTC.

Required for a reminder that has no task, or whose task has neither a start nor a due date.

Rejected with 400 when the task already has a start or due date: the reminder then fires from the task's own schedule, and a when of its own would be ignored. Send leads alone in that case.

recurrence: Recurrence

(Optional) How this reminder repeats; when is the first occurrence.

Rejected with 400 on a reminder whose task has a start or due date — it then repeats with its task's schedule, so a rule of its own would be ignored.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Omit it for a single notification at the fire time, which is the default ([{"minutes": 0}]).

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

name: string

(Optional) Text to show instead of the default message. Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

partner: string

(Optional) OID of the external team to share this reminder with; it then reaches every member of the project and of that team.

Only a project's reminder can carry one, and it cannot be combined with a members list ([] included) — both are 400. Without a task, it must be one of the project's external teams (400 otherwise). On a reminder attached to a task, it must be the team the task is shared with — the task's partner, or the nearest parent task's if it has none — or be omitted; any other value, and any value for a task not shared with a team, is 400.

An external team member shares a reminder with every member only through their own team. With members null, they must set partner to one of their teams; on a reminder attached to a task, that is the task's team. Otherwise 400 says what to send, as it does for a team of the project that isn't theirs.

Sharing with a team is part of Shared reminders, which needs the Premium plan or above (402 otherwise). Settable only when creating the reminder.

members: string[]

(Optional) Users who can see this reminder, and the only ones it notifies. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field — only the authenticated user. This is the default, except with partner: then every member of the project and of that team.
  • Pass null — every member of the owner. An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins.
  • Pass a list — only those users.

Unlike a work's members, omitting the field does not mean every member: pass null explicitly for that.

Omitting it without partner, or naming only yourself (such as ["me"]), keeps the reminder yours; anything else shares it — the Shared reminders feature, which needs the Premium plan or above (402 otherwise).

Rejected with 400 when a listed user is not a member of the owner, when a non-empty list does not include the authenticated user, or when partner is also set. On a reminder attached to a task, every listed user must also be able to see the task (400 naming those who can't): a project member sees every task, but an external team member only the tasks shared with their team. A guest sees only the reminders naming them, and creates none (403: a reminder takes write access).

Settable only when creating the reminder. It cannot be changed afterwards, so recreate the reminder to change who can see it. A personal reminder (created under -) is always its owner's alone, so no one else can be named.

Request Example
{
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill**",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created reminder record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project.

402 Payment Required

Payment Required — reminders need a Professional plan or above, and Shared reminders (members other than yourself, or partner) need Premium or above.

403 Forbidden

Forbidden — caller lacks permission to create a reminder here (a guest included: a reminder takes write access).

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a reminder by OID.

GET /reminder/{oid}

Returns the reminder with the given OID.

A reminder has no ID of its own, so this is the only way to fetch one; the /id/ forms address its owner, not the reminder.

oid: string
in path

OID of the reminder.

200 OK

OK — reminder record.

403 Forbidden

Forbidden — the reminder does not name the caller among those who can see it.

404 Not Found

Not Found — reminder does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List a task's reminders, by ID.

GET /reminder/list/id/task/{projectId}/{taskId}

Returns the reminders the caller can see on the given task.

A guest sees only the reminders naming them. A visitor of a public project who is not a member sees none, as in the project view.

projectId: string
in path

ID of the project the task belongs to.

taskId: integer
in path

ID of the task, an integer unique within its project.

limit: string
in query

(Optional) Page size, 1..1000. Omit it to return every reminder in one bare array, which is the default; pass no to ask for that explicitly.

With ?limit=N, the last item of the response carries an extra cursor field when more reminders remain; pass it back as ?cursor= for the next page. The last page carries none, which is how you know you are done. Nothing carries one in an unpaginated response.

cursor: string
in query

(Optional) Resume after this item. Pass the cursor of the last item of the previous page, verbatim.

Reminders are ordered by oid. That order is stable, but it is not chronological — do not read it as oldest-first, and sort by the field you care about after fetching.

timing: string standalone, anchored
in query

(Optional) Lists only the reminders that fire:

  • standalone: at their own when — those with no task, or on a task with neither a start nor a due date.
  • anchored: from their task's due date, or its start date if it has no due date. Their when is omitted.

Omit it to list both. ?timing=standalone&status=active lists the reminders still to fire at a time of their own, e.g. to sync them to a calendar.

status: string active, all
in query

(Optional) Which reminders to list:

  • active: only those with a notification still to come — not one whose notifications are all past, nor one on a completed or archived task.
  • all (default): every reminder.

A page still holds limit reminders while that many remain.

200 OK

OK — list of reminder records (may be empty).

400 Bad Request

Bad Request — invalid limit, cursor, timing or status.

403 Forbidden

Forbidden — caller lacks permission to read the task's project, such as one not granted to this app.

404 Not Found

Not Found — the task does not exist, is in the trash, or the caller can't see the task (an external team member can't see one that isn't shared with their team).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "task": {
      "url": "https://quire.io/w/my_project/42",
      "id": 42,
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "when": "2027-01-15T09:00:00.000Z",
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "leads": [
      {
        "minutes": 30,
        "days": 1,
        "at": "09:00"
      }
    ],
    "nameText": "Pay the bill",
    "nameHtml": "Pay the <strong>bill</strong>",
    "name": "Pay the **bill**",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "owner": {
      "type": "Project",
      "url": "https://quire.io/w/prj_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List reminders by owner ID.

GET /reminder/list/id/{ownerType}/{ownerId}

Returns the reminders the caller can see under the given owner (by ID).

A project's list includes the reminders on its tasks, not only the task-less ones; narrow it with timing and status. Reminders on a task that is in the trash are left out, since there is nothing to act on while it is there; they come back if the task is restored, and stay reachable by OID meanwhile.

For a single task's reminders, use GET /reminder/list/id/task/{projectId}/{taskId}.

A guest sees only the reminders naming them. A visitor of a public project who is not a member sees none, as in the project view.

ownerType: string
in path

What the reminders belong to: project, organization, folder, or smart-folder. Always required.

ownerId: string
in path

ID of what the reminders belong to. Pass - with ownerType project for My Tasks.

limit: string
in query

(Optional) Page size, 1..1000. Omit it to return every reminder in one bare array, which is the default; pass no to ask for that explicitly.

With ?limit=N, the last item of the response carries an extra cursor field when more reminders remain; pass it back as ?cursor= for the next page. The last page carries none, which is how you know you are done. Nothing carries one in an unpaginated response.

cursor: string
in query

(Optional) Resume after this item. Pass the cursor of the last item of the previous page, verbatim.

Reminders are ordered by oid. That order is stable, but it is not chronological — do not read it as oldest-first, and sort by the field you care about after fetching.

timing: string standalone, anchored
in query

(Optional) Lists only the reminders that fire:

  • standalone: at their own when — those with no task, or on a task with neither a start nor a due date.
  • anchored: from their task's due date, or its start date if it has no due date. Their when is omitted.

Omit it to list both. ?timing=standalone&status=active lists the reminders still to fire at a time of their own, e.g. to sync them to a calendar.

status: string active, all
in query

(Optional) Which reminders to list:

  • active: only those with a notification still to come — not one whose notifications are all past, nor one on a completed or archived task.
  • all (default): every reminder.

A page still holds limit reminders while that many remain.

200 OK

OK — list of reminder records (may be empty).

400 Bad Request

Bad Request — invalid limit, cursor, timing or status.

403 Forbidden

Forbidden — caller lacks permission to read this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "task": {
      "url": "https://quire.io/w/my_project/42",
      "id": 42,
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "when": "2027-01-15T09:00:00.000Z",
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "leads": [
      {
        "minutes": 30,
        "days": 1,
        "at": "09:00"
      }
    ],
    "nameText": "Pay the bill",
    "nameHtml": "Pay the <strong>bill</strong>",
    "name": "Pay the **bill**",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "owner": {
      "type": "Project",
      "url": "https://quire.io/w/prj_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List reminders by owner OID.

GET /reminder/list/{ownerType}/{ownerOid}

Returns the reminders the caller can see under the given owner.

A project's list includes the reminders on its tasks, not only the task-less ones; narrow it with timing and status. Reminders on a task that is in the trash are left out, since there is nothing to act on while it is there; they come back if the task is restored, and stay reachable by OID meanwhile. For a single task's, use ownerType task.

A guest sees only the reminders naming them. A visitor of a public project who is not a member sees none, as in the project view.

ownerType: string
in path

What the reminder belongs to: project, organization, folder, smart-folder, or task.

Always required; it doesn't default to project.

With task, the reminder is attached to that task and belongs to the task's project. A reminder cannot be moved to another task afterwards, and the task is chosen here rather than in the body — there is no task field to send.

ownerOid: string
in path

OID of what the reminder belongs to — a project, organization, folder, smart folder, or task, per ownerType.

Pass - with ownerType project for My Tasks, i.e. a personal reminder, visible to nobody else.

limit: string
in query

(Optional) Page size, 1..1000. Omit it to return every reminder in one bare array, which is the default; pass no to ask for that explicitly.

With ?limit=N, the last item of the response carries an extra cursor field when more reminders remain; pass it back as ?cursor= for the next page. The last page carries none, which is how you know you are done. Nothing carries one in an unpaginated response.

cursor: string
in query

(Optional) Resume after this item. Pass the cursor of the last item of the previous page, verbatim.

Reminders are ordered by oid. That order is stable, but it is not chronological — do not read it as oldest-first, and sort by the field you care about after fetching.

timing: string standalone, anchored
in query

(Optional) Lists only the reminders that fire:

  • standalone: at their own when — those with no task, or on a task with neither a start nor a due date.
  • anchored: from their task's due date, or its start date if it has no due date. Their when is omitted.

Omit it to list both. ?timing=standalone&status=active lists the reminders still to fire at a time of their own, e.g. to sync them to a calendar.

status: string active, all
in query

(Optional) Which reminders to list:

  • active: only those with a notification still to come — not one whose notifications are all past, nor one on a completed or archived task.
  • all (default): every reminder.

A page still holds limit reminders while that many remain.

200 OK

OK — list of reminder records (may be empty).

400 Bad Request

Bad Request — invalid limit, cursor, timing or status.

403 Forbidden

Forbidden — caller lacks permission to read this owner.

404 Not Found

Not Found — the owner does not exist, or, for a task, it is in the trash or the caller can't see it (an external team member can't see one that isn't shared with their team).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "oid": "iDsPd.QP_qM.hN.Trymukn8b",
    "task": {
      "url": "https://quire.io/w/my_project/42",
      "id": 42,
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "when": "2027-01-15T09:00:00.000Z",
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "leads": [
      {
        "minutes": 30,
        "days": 1,
        "at": "09:00"
      }
    ],
    "nameText": "Pay the bill",
    "nameHtml": "Pay the <strong>bill</strong>",
    "name": "Pay the **bill**",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "owner": {
      "type": "Project",
      "url": "https://quire.io/w/prj_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Update a reminder by OID.

PUT /reminder/{oid}

Updates the reminder with the given OID.

Only when, recurrence, leads and name can be changed. What the reminder belongs to, the task it is attached to, its members and its partner are all fixed when it is created — recreate the reminder to change any of them.

oid: string
in path

OID of the reminder to update.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full reminder record.
  • compact: the OID only ({"oid": "…"}). Saves payload, tokens, and a server-side reload + render, so prefer it when you only need the OID to chain follow-up calls.

Any other value returns 400 Bad Request.

when: string

(Optional) When this reminder fires (UTC, ISO 8601).

Rejected with 400 on a reminder whose task has a start or due date — it fires from the task's schedule, so a when of its own would be ignored — and also when set to null on one that has no other time to fire from.

recurrence: Recurrence

(Optional) How this reminder repeats; null stops it repeating.

Rejected with 400 on a reminder whose task has a start or due date, for the same reason as when.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Replaces the current list.

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

name: string

(Optional) Text to show instead of the default message. Pass null to fall back to the default.

Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

Request Example
{
  "when": "2027-03-20T18:30:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill** today"
}
200 OK

OK — updated reminder record.

400 Bad Request

Bad Request — body validation failed, or a field that cannot be changed was sent.

403 Forbidden

Forbidden — the reminder does not name the caller among those who can see it, or the caller lacks write access (a guest named in it can read but not change or delete it).

404 Not Found

Not Found — reminder does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Delete a reminder by OID.

DELETE /reminder/{oid}

Deletes the reminder with the given OID. Unlike a task or a sublist, a reminder is not moved to the trash and cannot be restored.

Note: Returns 204 No Content regardless of whether the reminder exists.

oid: string
in path

OID of the reminder to delete.

204 No Content

No Content

403 Forbidden

Forbidden — the reminder does not name the caller among those who can see it, or the caller lacks write access (a guest named in it can read but not change or delete it).

Response Content-Types: application/json

status

Task statuses represent progress values for tasks.

Add a new task status (by project OID).

POST /status/{projectOid}

Creates a new task status in the specified project and returns it. A value already in use in the project returns 409. A name already in use, ignoring case, gets a numbered suffix, e.g. Doing (1).

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

Example: {"name": "Review", "value": 70, "color": "35"}.

A status over the plan's status limit returns 402.

projectOid: string
in path

Project OID to add the status to.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"value": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Status color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

name: string

Display name of the status.

value: integer

Non-negative integer indicating progress. Must be unique within its context (e.g., project); a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually.

Request Example
{
  "color": "35",
  "name": "Doing",
  "value": 50
}
200 OK

OK — newly created status.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — plan's status limit is reached (code 469).

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a status with this value already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

Add a new task status (by project ID).

POST /status/id/{projectId}

Creates a new task status in the specified project and returns it. A value already in use in the project returns 409. A name already in use, ignoring case, gets a numbered suffix, e.g. Doing (1).

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

Example: {"name": "Review", "value": 70, "color": "35"}.

A status over the plan's status limit returns 402.

projectId: string
in path

Project ID to add the status to.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"value": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Status color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

name: string

Display name of the status.

value: integer

Non-negative integer indicating progress. Must be unique within its context (e.g., project); a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually.

Request Example
{
  "color": "35",
  "name": "Doing",
  "value": 50
}
200 OK

OK — newly created status.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required — plan's status limit is reached (code 469).

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

404 Not Found

Not Found — project does not exist.

409 Conflict

Conflict — a status with this value already exists.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

Get a task status by value (project OID).

GET /status/{projectOid}/{value}

Returns the status record matching the given value in the specified project.

projectOid: string
in path

Project OID.

value: integer
in path

Status value to fetch.

200 OK

OK — status record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project or status does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

Get a task status by value (project ID).

GET /status/id/{projectId}/{value}

Returns the status record matching the given value in the specified project.

projectId: string
in path

Project ID.

value: integer
in path

Status value to fetch.

200 OK

OK — status record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project or status does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

List all statuses (by project ID).

GET /status/list/id/{projectId}

Returns all status records in the specified project.

projectId: string
in path

Project ID.

200 OK

OK — list of statuses (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "color": "35",
    "name": "Doing",
    "value": 50
  }
]

List all statuses (by project OID).

GET /status/list/{projectOid}

Returns all status records in the specified project.

projectOid: string
in path

Project OID.

200 OK

OK — list of statuses (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "color": "35",
    "name": "Doing",
    "value": 50
  }
]

Update a task status (by project OID).

PUT /status/{projectOid}/{value}

Updates an existing status and returns the complete updated record. Omitted body fields are left unchanged. A name already in use, ignoring case, gets a numbered suffix, e.g. Doing (1). The value of 0 (the initial status) and 100 (completed) can't change (403); changing value to one already in use returns 409. With ?return=compact, the response holds the value after the update.

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

projectOid: string
in path

Project OID.

value: integer
in path

Status value to update.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"value": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Status color index from Quire’s predefined palette (two digits: first 0–5, second 0–7; e.g., 35).

name: string

(Optional) New display name for the status.

value: integer

(Optional) New numeric status value. Non-negative integer indicating progress. Must be unique within the project; a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually. The value of 0 (the initial status) and 100 (completed) can't change.

Request Example
{
  "color": "35",
  "name": "Later",
  "value": 50
}
200 OK

OK — updated status record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

404 Not Found

Not Found — project or status does not exist.

409 Conflict

Conflict — another status already has the new value.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

Update a task status (by project ID).

PUT /status/id/{projectId}/{value}

Updates an existing status and returns the complete updated record. Omitted body fields are left unchanged. A name already in use, ignoring case, gets a numbered suffix, e.g. Doing (1). The value of 0 (the initial status) and 100 (completed) can't change (403); changing value to one already in use returns 409. With ?return=compact, the response holds the value after the update.

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

projectId: string
in path

Project ID.

value: integer
in path

Status value to update.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"value": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Status color index from Quire’s predefined palette (two digits: first 0–5, second 0–7; e.g., 35).

name: string

(Optional) New display name for the status.

value: integer

(Optional) New numeric status value. Non-negative integer indicating progress. Must be unique within the project; a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually. The value of 0 (the initial status) and 100 (completed) can't change.

Request Example
{
  "color": "35",
  "name": "Later",
  "value": 50
}
200 OK

OK — updated status record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

404 Not Found

Not Found — project or status does not exist.

409 Conflict

Conflict — another status already has the new value.

Response Content-Types: application/json
Response Example (200 OK)
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

Delete a task status (by project OID).

DELETE /status/{projectOid}/{value}

Deletes the specified status; its tasks move to the next lower status. 0 (the initial status) and 100 (completed) can't be deleted (403).

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

Returns 204 No Content, also when the status doesn't exist.

projectOid: string
in path

Project OID.

value: integer
in path

Status value to delete.

204 No Content

No Content — status deleted (or already absent).

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

Response Content-Types: application/json

Delete a task status (by project ID).

DELETE /status/id/{projectId}/{value}

Deletes the specified status; its tasks move to the next lower status. 0 (the initial status) and 100 (completed) can't be deleted (403).

Requires a user who can manage the project's statuses, and an app with the Manage statuses permission; otherwise 403. An external team's members can't.

Returns 204 No Content, also when the status doesn't exist.

projectId: string
in path

Project ID.

value: integer
in path

Status value to delete.

204 No Content

No Content — status deleted (or already absent).

403 Forbidden

Forbidden — the user can't manage the project's statuses, or the app lacks the Manage statuses permission.

Response Content-Types: application/json

storage

A simple key–value storage for application-specific data. Each value is any JSON value, kept per authorization of your app. A key is addressed as /storage/{name}: unlike other resources, there is no /storage/id/... form (404).

Get a stored value.

GET /storage/{name}

Returns the value stored under name, exactly as it was stored: any JSON value, such as an object, array, string or number. 404 if there is none.

Example: after PUT /storage/latest with the body {"project": "my_project"}, GET /storage/latest returns {"project": "my_project"}.

Stored data belongs to the authorization — the user's grant to the app, behind its refresh token — not to the access token: a refreshed or new access token of the same authorization sees the same data. It is deleted when the authorization is revoked or expires, or when the user is deleted.

Limits:

  • Keys per authorization, by the user's best plan (a trial doesn't count): Free 15, Professional 100, Premium 250, Enterprise 1,000. A PUT adding a key beyond that returns 402 (code 469); delete keys or upgrade.
  • A value is at most 4 KiB as JSON; a larger one returns 413.
  • Each call costs 1 rate-limit unit, counted against the organization of that best plan; a user in no organization has a bucket of their own, at the Free plan's limits. Over the limit, 429 with Retry-After.
name: string
in path

The key. Any string except id and list, and one starting with :}>.

200 OK

OK — the stored value, as it was stored.

404 Not Found

Not Found — no value is stored under this key.

429 Too Many Requests

Too Many Requests — rate limit reached. Honor Retry-After.

Response Content-Types: application/json
Response Example (200 OK)
"object"

List all stored entries.

GET /storage/list

Returns the stored entries of the current authorization.

The response is one JSON object mapping each key to its value, as it was stored — at most 20 entries, by key ascending, and {} if none. There is no paging: with more than 20 keys, narrow the listing with GET /storage/list/{prefix}.

Example: {"latest": {"project": "my_project"}, "theme": "dark"}.

Stored data belongs to the authorization — the user's grant to the app, behind its refresh token — not to the access token: a refreshed or new access token of the same authorization sees the same data. It is deleted when the authorization is revoked or expires, or when the user is deleted.

Limits:

  • Keys per authorization, by the user's best plan (a trial doesn't count): Free 15, Professional 100, Premium 250, Enterprise 1,000. A PUT adding a key beyond that returns 402 (code 469); delete keys or upgrade.
  • A value is at most 4 KiB as JSON; a larger one returns 413.
  • Each call costs 1 rate-limit unit, counted against the organization of that best plan; a user in no organization has a bucket of their own, at the Free plan's limits. Over the limit, 429 with Retry-After.

OK — key-to-value object of the stored entries (may be {}).

429 Too Many Requests

Too Many Requests — rate limit reached. Honor Retry-After.

Response Content-Types: application/json
Response Example (200 OK)
"object"

List stored entries by prefix.

GET /storage/list/{prefix}

Returns the stored entries whose keys start with prefix. The prefix is matched literally: % and _ are not wildcards. Use it to group values under a common key prefix.

The response is one JSON object mapping each key to its value, as it was stored — at most 20 entries, by key ascending, and {} if none. There is no paging: with more than 20 keys, narrow the listing with GET /storage/list/{prefix}.

Example: {"latest": {"project": "my_project"}, "theme": "dark"}.

Stored data belongs to the authorization — the user's grant to the app, behind its refresh token — not to the access token: a refreshed or new access token of the same authorization sees the same data. It is deleted when the authorization is revoked or expires, or when the user is deleted.

Limits:

  • Keys per authorization, by the user's best plan (a trial doesn't count): Free 15, Professional 100, Premium 250, Enterprise 1,000. A PUT adding a key beyond that returns 402 (code 469); delete keys or upgrade.
  • A value is at most 4 KiB as JSON; a larger one returns 413.
  • Each call costs 1 rate-limit unit, counted against the organization of that best plan; a user in no organization has a bucket of their own, at the Free plan's limits. Over the limit, 429 with Retry-After.
prefix: string
in path

Key prefix to match.

OK — key-to-value object of the matching entries (may be {}).

429 Too Many Requests

Too Many Requests — rate limit reached. Honor Retry-After.

Response Content-Types: application/json
Response Example (200 OK)
"object"

Create or update a stored value.

PUT /storage/{name}

Stores the request body under name, replacing any value already there. The body is the value itself: any JSON value, such as an object, array, string or number. A body of null, or an empty one, deletes the key instead.

Returns 204 No Content. Example: after PUT /storage/latest with the body {"project": "my_project"}, GET /storage/latest returns {"project": "my_project"}.

Stored data belongs to the authorization — the user's grant to the app, behind its refresh token — not to the access token: a refreshed or new access token of the same authorization sees the same data. It is deleted when the authorization is revoked or expires, or when the user is deleted.

Limits:

  • Keys per authorization, by the user's best plan (a trial doesn't count): Free 15, Professional 100, Premium 250, Enterprise 1,000. A PUT adding a key beyond that returns 402 (code 469); delete keys or upgrade.
  • A value is at most 4 KiB as JSON; a larger one returns 413.
  • Each call costs 1 rate-limit unit, counted against the organization of that best plan; a user in no organization has a bucket of their own, at the Free plan's limits. Over the limit, 429 with Retry-After.
name: string
in path

The key. Any string except id and list, and one starting with :}>.

Request Example
"object"
204 No Content

No Content — value stored (or deleted if the body is null or empty).

400 Bad Request

Bad Request — the key is id or list, or starts with :}>.

402 Payment Required

Payment Required — the key limit of the plan is reached (code 469). Delete keys or upgrade.

413 Request Entity Too Large

Payload Too Large — the value exceeds 4 KiB as JSON.

418

Not Valid JSON Content — the body isn't valid JSON.

429 Too Many Requests

Too Many Requests — rate limit reached. Honor Retry-After.

Response Content-Types: application/json

Delete a stored value.

DELETE /storage/{name}

Deletes the value stored under name.

Note: Returns 204 No Content regardless of whether the value exists.

Stored data belongs to the authorization — the user's grant to the app, behind its refresh token — not to the access token: a refreshed or new access token of the same authorization sees the same data. It is deleted when the authorization is revoked or expires, or when the user is deleted.

Limits:

  • Keys per authorization, by the user's best plan (a trial doesn't count): Free 15, Professional 100, Premium 250, Enterprise 1,000. A PUT adding a key beyond that returns 402 (code 469); delete keys or upgrade.
  • A value is at most 4 KiB as JSON; a larger one returns 413.
  • Each call costs 1 rate-limit unit, counted against the organization of that best plan; a user in no organization has a bucket of their own, at the Free plan's limits. Over the limit, 429 with Retry-After.
name: string
in path

The key. Any string except id and list, and one starting with :}>.

204 No Content

No Content

429 Too Many Requests

Too Many Requests — rate limit reached. Honor Retry-After.

Response Content-Types: application/json

sublist

A sublist is a collection of tasks, representing a subset of tasks from a larger scope. To list the tasks of a project's sublist, use GET /task/search/id/{projectId}?sublist={sublistId}.

Create a sublist by owner OID.

POST /sublist/{ownerType}/{ownerOid}

Creates a sublist under the given owner — a project, organization, folder, or smart-folder — and returns it.

Example — POST /sublist/id/project/my_project:

{
  "name": "Sprint 12",
  "includes": ["2MmYOpJH_ZLeehIjjytH1Rwr"],
  "due": "2026-11-30"
}

includes adds those tasks with all their subtasks. To start with every task instead, pass "all": true, then leave tasks out by updating the sublist with changes.

Returns 402 if the plan's sublist limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /abc123 is equivalent to /project/abc123.

ownerOid: string
in path

OID of the owner the new sublist will belong to.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

all: boolean

(Optional) Whether every task belongs to the sublist by default. Default: false — only the tasks in includes are in it, with their subtasks. With true, every task of the owner is in it; leave tasks out afterwards by updating the sublist with changes ("exclude": true). Settable only when creating the sublist.

includes: string[]

(Optional) List of task OIDs to include in this sublist. All descendants of the specified tasks will be included as well.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

start: string

(Optional) Target start date: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "all": false,
  "includes": [
    "string"
  ],
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created sublist record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — sublist quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a sublist under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Create a sublist by owner ID.

POST /sublist/id/{ownerType}/{ownerId}

Creates a sublist under the given owner — a project, organization, folder, or smart-folder — and returns it.

Example — POST /sublist/id/project/my_project:

{
  "name": "Sprint 12",
  "includes": ["2MmYOpJH_ZLeehIjjytH1Rwr"],
  "due": "2026-11-30"
}

includes adds those tasks with all their subtasks. To start with every task instead, pass "all": true, then leave tasks out by updating the sublist with changes.

Returns 402 if the plan's sublist limit is reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /id/foo is equivalent to /id/project/foo.

ownerId: string
in path

ID of the owner the new sublist will belong to.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

all: boolean

(Optional) Whether every task belongs to the sublist by default. Default: false — only the tasks in includes are in it, with their subtasks. With true, every task of the owner is in it; leave tasks out afterwards by updating the sublist with changes ("exclude": true). Settable only when creating the sublist.

includes: string[]

(Optional) List of task OIDs to include in this sublist. All descendants of the specified tasks will be included as well.

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

start: string

(Optional) Target start date: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

Request Example
{
  "all": false,
  "includes": [
    "string"
  ],
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "members": "[\"me\", \"john\"]"
}
200 OK

OK — created sublist record.

400 Bad Request

Bad Request — body validation failed, for example a partner that isn't an external team of the project (or any, when the owner isn't a project), or none from an external team member sharing with every member.

402 Payment Required

Payment Required — sublist quota reached.

403 Forbidden

Forbidden — caller lacks permission to create a sublist under this owner.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a sublist by ID.

GET /sublist/id/{ownerType}/{ownerId}/{sublistId}

Returns the sublist record.

To list its tasks, call GET /task/search/id/{projectId}?sublist={sublistId} (sublist also takes the OID). It works for a project's sublist only, returns 30 tasks unless you pass limit, and gives no cursor.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

ID of the owner the sublist belongs to.

sublistId: string
in path

ID of the sublist.

200 OK

OK — sublist record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Get a sublist by OID.

GET /sublist/{oid}

Returns the sublist record.

To list its tasks, call GET /task/search/id/{projectId}?sublist={sublistId} (sublist also takes the OID). It works for a project's sublist only, returns 30 tasks unless you pass limit, and gives no cursor.

oid: string
in path

OID of the sublist.

200 OK

OK — sublist record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

List sublists by owner ID.

GET /sublist/list/id/{ownerType}/{ownerId}

Returns the owner's sublists that the caller can see; one shown to selected members only is left out for the others. Archived sublists are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /list/id/foo is equivalent to /list/id/project/foo.

ownerId: string
in path

ID of the owner.

200 OK

OK — list of sublist records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?sublist=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "all": false,
    "start": "2024-01-02",
    "due": "2024-05-25",
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

List sublists by owner OID.

GET /sublist/list/{ownerType}/{ownerOid}

Returns the owner's sublists that the caller can see; one shown to selected members only is left out for the others. Archived sublists are included (they carry archivedAt); removed ones are not.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /list/abc123 is equivalent to /list/project/abc123.

ownerOid: string
in path

OID of the owner.

200 OK

OK — list of sublist records (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — owner does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "url": "https://quire.io/w/my_project?sublist=Highlight101",
    "nameText": "Highlight 101",
    "nameHtml": "Highlight 101",
    "name": "Highlight 101",
    "id": "Highlight101",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "partner": {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "all": false,
    "start": "2024-01-02",
    "due": "2024-05-25",
    "archivedAt": "2020-02-22T02:06:58.158Z",
    "members": [
      {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "private": true,
    "owner": {
      "url": "https://quire.io/w/prj_id",
      "type": "Project",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]

Undo the removal of a sublist by ID.

PUT /sublist/undo-remove/id/{ownerType}/{ownerId}/{sublistId}

Restores a previously-removed sublist. Idempotent: if the sublist is not currently removed, this is a no-op and returns the current sublist record.

Subject to the sublist-per-owner quota: may return 402 Payment Required if the plan's sublist limit is already reached.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /undo-remove/id/foo/bar is equivalent to /undo-remove/id/project/foo/bar.

ownerId: string
in path

ID of the owner.

sublistId: string
in path

ID of the sublist to restore.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored sublist record.

402 Payment Required

Payment Required — sublist quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this sublist.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of a sublist by OID.

PUT /sublist/undo-remove/{oid}

Restores a previously-removed sublist. Idempotent: if the sublist is not currently removed, this is a no-op and returns the current sublist record.

Subject to the sublist-per-owner quota: may return 402 Payment Required if the plan's sublist limit is already reached.

oid: string
in path

OID of the sublist to restore.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

200 OK

OK — restored sublist record.

402 Payment Required

Payment Required — sublist quota reached.

403 Forbidden

Forbidden — caller lacks permission to restore this sublist.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a sublist by ID.

PUT /sublist/id/{ownerType}/{ownerId}/{sublistId}

Updates an existing sublist and returns the complete updated record.

To archive or unarchive, set archived: true or archived: false in the body.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

ID of the owner.

sublistId: string
in path

ID of the sublist to update.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

start: string

(Optional) Target start date for this record: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date for this record: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

changes: Change

(Optional) Tasks to add to or remove from this sublist, applied in order. Each item is {"task": "<task OID>", "exclude": false, "single": false}:

  • exclude: true removes the task instead of adding it.
  • single: true changes only the task itself; by default its subtasks follow it.

A task that doesn't exist is skipped. Example — add one task with its subtasks and leave another out:

[
  {"task": "2MmYOpJH_ZLeehIjjytH1Rwr"},
  {"task": "q8Rn1zX5bKcT0wGvJmLd3PaE", "exclude": true}
]
private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "start": "2024-01-02",
  "due": "2024-05-25",
  "changes": "[{\"task\": \"2MmYOpJH_ZLeehIjjytH1Rwr\"}, {\"task\": \"q8Rn1zX5bKcT0wGvJmLd3PaE\", \"exclude\": true}]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated sublist record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this sublist.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Update a sublist by OID.

PUT /sublist/{oid}

Updates an existing sublist and returns the complete updated record.

To archive or unarchive, set archived: true or archived: false in the body.

oid: string
in path

OID of the sublist to update.

return: string full, compact
in query

(Optional) Response shape: full (default) returns the full sublist record; compact returns only {"oid": "…", "id": "…"}, which is cheaper — use it when you don't need the record back. Any other value returns 400 Bad Request.

start: string

(Optional) Target start date for this record: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date for this record: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

changes: Change

(Optional) Tasks to add to or remove from this sublist, applied in order. Each item is {"task": "<task OID>", "exclude": false, "single": false}:

  • exclude: true removes the task instead of adding it.
  • single: true changes only the task itself; by default its subtasks follow it.

A task that doesn't exist is skipped. Example — add one task with its subtasks and leave another out:

[
  {"task": "2MmYOpJH_ZLeehIjjytH1Rwr"},
  {"task": "q8Rn1zX5bKcT0wGvJmLd3PaE", "exclude": true}
]
private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Request Example
{
  "start": "2024-01-02",
  "due": "2024-05-25",
  "changes": "[{\"task\": \"2MmYOpJH_ZLeehIjjytH1Rwr\"}, {\"task\": \"q8Rn1zX5bKcT0wGvJmLd3PaE\", \"exclude\": true}]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}
200 OK

OK — updated sublist record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to modify this sublist.

404 Not Found

Not Found — sublist does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Delete a sublist by ID.

DELETE /sublist/id/{ownerType}/{ownerId}/{sublistId}

Removes the sublist. Restore it with PUT /sublist/undo-remove/id/{ownerType}/{ownerId}/{sublistId} (or /sublist/undo-remove/{oid}).

Returns 204 No Content, also when the sublist does not exist.

ownerType: string
in path

Owner type. One of project, organization, folder, or smart-folder. If omitted, project is assumed. For example, /id/my_project/1234 is equivalent to /id/project/my_project/1234.

ownerId: string
in path

ID of the owner.

sublistId: string
in path

ID of the sublist to delete.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this sublist.

Response Content-Types: application/json

Delete a sublist by OID.

DELETE /sublist/{oid}

Removes the sublist. Restore it with PUT /sublist/undo-remove/id/{ownerType}/{ownerId}/{sublistId} (or /sublist/undo-remove/{oid}).

Returns 204 No Content, also when the sublist does not exist.

oid: string
in path

OID of the sublist to delete.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to remove this sublist.

Response Content-Types: application/json

tag

A tag is a label that can be attached to a task in Quire.

tag

Create a tag.

POST /tag/{projectOid}

Creates a new tag in the specified project and returns it. With global: true, the tag belongs to the project's organization and is available in all its projects; My Tasks (-) can't have one (403).

Requires a user who can manage the project's tags, and an app with the Manage tags permission; otherwise 403. Creating a global tag, or making a tag global, also takes the right to manage the organization's tags; updating or deleting a global tag takes only that right.

projectOid: string
in path

OID of the project to add the new tag to. Specify "-" to add it to personal tasks (My Tasks, not in a specific project).

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"oid": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Tag color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

global: boolean

(Optional) Whether this tag is global (available in all projects of the project's organization). If omitted, the tag is not global. true requires the right to manage the organization's tags; otherwise 403.

name: string

Display name of the tag.

Request Example
{
  "color": "35",
  "global": true,
  "name": "Later"
}
200 OK
Tag

OK — newly created tag.

400 Bad Request

Bad Request — body validation failed (e.g., name missing or too long).

403 Forbidden

Forbidden — the user can't manage the tags, or the app lacks the Manage tags permission.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "global": true,
  "color": "35",
  "name": "Later",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
tag

Create a tag.

POST /tag/id/{projectId}

Creates a new tag in the specified project and returns it. With global: true, the tag belongs to the project's organization and is available in all its projects; My Tasks (-) can't have one (403).

Requires a user who can manage the project's tags, and an app with the Manage tags permission; otherwise 403. Creating a global tag, or making a tag global, also takes the right to manage the organization's tags; updating or deleting a global tag takes only that right.

projectId: string
in path

ID of the project to add the new tag to. Specify "-" to add it to personal tasks (My Tasks, not in a specific project).

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"oid": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Tag color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

global: boolean

(Optional) Whether this tag is global (available in all projects of the project's organization). If omitted, the tag is not global. true requires the right to manage the organization's tags; otherwise 403.

name: string

Display name of the tag.

Request Example
{
  "color": "35",
  "global": true,
  "name": "Later"
}
200 OK
Tag

OK — newly created tag.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user can't manage the tags, or the app lacks the Manage tags permission.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "global": true,
  "color": "35",
  "name": "Later",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
tag

Get a tag.

GET /tag/{oid}

Returns the complete tag record for the given OID.

oid: string
in path

OID of the tag to fetch.

200 OK
Tag

OK — tag record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — tag does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "global": true,
  "color": "35",
  "name": "Later",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
tag

List tags by project ID.

GET /tag/list/id/{projectId}

Returns the tags of the specified project, and the global tags of its organization.

projectId: string
in path

ID of the project. Specify "-" to list tags used in personal tasks (My Tasks, not in a specific project).

200 OK
Tag

OK — list of tags (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "global": true,
    "color": "35",
    "name": "Later",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "project": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]
tag

List tags by project OID.

GET /tag/list/{projectOid}

Returns the tags of the specified project, and the global tags of its organization.

projectOid: string
in path

OID of the project. Specify "-" to list tags used in personal tasks (My Tasks, not in a specific project).

200 OK
Tag

OK — list of tags (may be empty).

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "global": true,
    "color": "35",
    "name": "Later",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "project": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "createdBy": "#/definitions/SimpleIdentity",
    "createdAt": "2018-12-22T02:06:58.158Z"
  }
]
tag

Update a tag.

PUT /tag/{oid}

Updates an existing tag and returns the complete updated record. Omitted body fields are left unchanged.

Requires a user who can manage the project's tags, and an app with the Manage tags permission; otherwise 403. Creating a global tag, or making a tag global, also takes the right to manage the organization's tags; updating or deleting a global tag takes only that right.

oid: string
in path

OID of the tag to update.

return: string full, compact
in query

(Optional) Response shape: full (default) for the full record, or compact for just {"oid": …}. Any other value returns 400 Bad Request.

color: string

(Optional) Tag color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 35, 57). NOT a CSS hex color.

global: boolean

(Optional) Whether the tag is global (available across projects). If set to false, you must also provide project.

project: string

(Optional) Project OID that this tag is limited to. Used only when global is explicitly set to false; ignored otherwise.

name: string

(Optional) New display name for the tag.

Request Example
{
  "color": "35",
  "global": true,
  "project": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "name": "Later"
}
200 OK
Tag

OK — updated tag record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — the user can't manage the tags, or the app lacks the Manage tags permission.

404 Not Found

Not Found — tag does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "global": true,
  "color": "35",
  "name": "Later",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}
tag

Delete a tag.

DELETE /tag/{oid}

Deletes the tag with the given OID.

Requires a user who can manage the project's tags, and an app with the Manage tags permission; otherwise 403. Creating a global tag, or making a tag global, also takes the right to manage the organization's tags; updating or deleting a global tag takes only that right.

Returns 204 No Content, also when the tag doesn't exist.

oid: string
in path

OID of the tag to delete.

204 No Content

No Content — tag deleted (or already absent).

403 Forbidden

Forbidden — the user can't manage the tags, or the app lacks the Manage tags permission.

Response Content-Types: application/json

task

Tasks are the basic units of work you and your team collaborate on.

Add a time log to a task by ID.

POST /task/add-timelog/id/{projectId}/{taskId}

Adds a time log to the task. The new log is credited to the authenticated caller unless user is supplied in the body.

Identity of a log is the triple (user, start, end). Sub-second precision in start / end is truncated to whole seconds.

On success returns the task's full timelogs array. If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example:

[
  {
    "start": "2026-04-26T09:00:00.000Z",
    "end": "2026-04-26T10:30:00.000Z",
    "billable": true,
    "note": "Pair-programming session",
    "user": { "oid": "u-123", "name": "John Doe" }
  }
]
projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

end: string

End timestamp (ISO 8601, UTC). Must be on or after start. Sub-second precision is truncated to whole seconds.

user: string

(Optional) User identifier (OID, ID, or email) the log is credited to. Omitted, null, or empty defaults to the authenticated caller. Unknown users return 400 Bad Request.

billable: boolean

(Optional) Whether this log is billable. Omitted or null defaults to true.

note: string

(Optional) Free-form note for the log. Omitted, null, or empty stores no note.

start: string

Start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds.

Request Example
{
  "end": "2026-04-26T10:30:00Z",
  "user": "john.doe@example.com",
  "billable": true,
  "note": "Pair-programming session",
  "start": "2026-04-26T09:00:00Z"
}
200 OK

OK — task's full timelogs array.

400 Bad Request

Bad Request — start / end missing or malformed, end precedes start, user is unknown, or a field has the wrong type.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — task does not exist.

409 Conflict

Conflict — a log with the same (user, start, end) already exists; use PUT /task/update-timelog/... to amend it.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (409 Conflict)
{
  "code": 429,
  "message": "Something went wrong."
}

Add a time log to a task by OID.

POST /task/add-timelog/{oid}

Adds a time log to the task. The new log is credited to the authenticated caller unless user is supplied in the body.

Identity of a log is the triple (user, start, end). Sub-second precision in start / end is truncated to whole seconds.

On success returns the task's full timelogs array. If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example:

[
  {
    "start": "2026-04-26T09:00:00.000Z",
    "end": "2026-04-26T10:30:00.000Z",
    "billable": true,
    "note": "Pair-programming session",
    "user": { "oid": "u-123", "name": "John Doe" }
  }
]

See also the by-ID form POST /task/add-timelog/id/{projectId}/{taskId}.

oid: string
in path

Task OID.

end: string

End timestamp (ISO 8601, UTC). Must be on or after start. Sub-second precision is truncated to whole seconds.

user: string

(Optional) User identifier (OID, ID, or email) the log is credited to. Omitted, null, or empty defaults to the authenticated caller. Unknown users return 400 Bad Request.

billable: boolean

(Optional) Whether this log is billable. Omitted or null defaults to true.

note: string

(Optional) Free-form note for the log. Omitted, null, or empty stores no note.

start: string

Start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds.

Request Example
{
  "end": "2026-04-26T10:30:00Z",
  "user": "john.doe@example.com",
  "billable": true,
  "note": "Pair-programming session",
  "start": "2026-04-26T09:00:00Z"
}
200 OK

OK — task's full timelogs array.

400 Bad Request

Bad Request — start / end missing or malformed, end precedes start, user is unknown, or a field has the wrong type.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — task does not exist.

409 Conflict

Conflict — a log with the same (user, start, end) already exists; use PUT /task/update-timelog/... to amend it.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (409 Conflict)
{
  "code": 429,
  "message": "Something went wrong."
}

Set or transition a task's approval state.

POST /task/approve/id/{projectId}/{taskId}

Sets the task's approval, or transitions it from its current state. The ?state= query parameter selects the transition:

  • request — request approval, or roll forward from approved / rejected / changes back to awaiting.
  • approve / reject / change — approver's decision.

The caller must be a claimer (for request) or an approver (for approve / reject / change) of the category. The original requester is preserved across approve / reject / change transitions.

Request body (optional). Supply a JSON object with a description field to post a companion comment on the task as a side effect of the approval call. Same shape as POST /comment: {"description": "<markdown>", "pinned": false, "asUser": false}. description is required when the body is supplied; pinned and asUser are optional.

The stored comment is a header, a blank line, then the supplied description. The header is a plain <category>: <status> line: the category's name, left out for the default category, then the status in the authorizing user's language (Awaiting approval, Approved, Rejected or Request changes in English). Don't parse it: its wording depends on the language. For example, {"description": "Please tweak the wording."} on a state=change call for the category legal, named Legal Review, stores Legal Review: Request changes\n\nPlease tweak the wording. Don't include the header in description yourself.

Without a body, approve / reject / change still log a comment holding only the header, as the apps do; request logs nothing. The created comment is not included in the response — call GET /comment/list/{taskOid} afterward to fetch it.

To cancel an approval, use DELETE /task/revoke-approval/id/{projectId}/{taskId} (or DELETE /task/revoke-approval/{oid}) — not this endpoint.

Returns 400 Bad Request if ?state= is missing or unknown, or the body has unknown fields, an empty description, or a non-object shape; 403 Forbidden if the caller isn't a claimer / approver; 404 Not Found if the task or ?category= doesn't exist.

Examples:

POST /task/approve/id/my_project/42?category=legal&state=approve
                  (empty body — records the approval and logs a header-only comment)
                  
                  POST /task/approve/id/my_project/42?category=legal&state=change
                  {"description": "Please tweak the wording."}
                  
                  POST /task/approve/iuRRiKoyrxdBFhFTTo?state=request
                  (by OID — requests approval in the default category)
                  
projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

state: string request, approve, reject, change
in query

Approval transition to apply: request requests approval (or rolls forward from a decided state back to awaiting); approve / reject / change records the approver's decision.

category: string
in query

(Optional) Approval category ID. Defaults to the project's default category (id "").

return: string full, compact
in query

(Optional) Response shape: full (default) returns the task's approval record; compact returns only the task's {"oid": …, "id": …}. Any other value returns 400 Bad Request.

description: string

Content of the companion comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Required if the body is supplied. The server prepends a <category>: <status> line (status in the authorizing user's language; no category name for the default category) and a blank line before this text, so this field should contain only the human-written message — do not include the header yourself.

pinned: boolean

(Optional) Whether to pin the companion comment on the task. Default: false.

asUser: boolean

(Optional) If true, the comment is attributed to the app rather than the authorizing user ( app-as-user, as the asUser flag on POST /comment). Default: false. Either way, the authorizing user, not the app, follows the task, as for any comment.

Request Example
{
  "description": "Please tweak the wording.",
  "pinned": false,
  "asUser": false
}
200 OK

successful operation

Response Content-Types: application/json
Response Example (200 OK)
{
  "toggledAt": "2026-04-24T10:05:00.000Z",
  "requester": "string",
  "requesterRef": {
    "id": "my_id",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "approverRef": "#/definitions/SimpleEntityWithId",
  "category": "legal",
  "approver": "string",
  "state": "awaiting"
}

Set or transition a task's approval state by OID.

POST /task/approve/{oid}

Sets the task's approval, or transitions it from its current state. The ?state= query parameter selects the transition:

  • request — request approval, or roll forward from approved / rejected / changes back to awaiting.
  • approve / reject / change — approver's decision.

The caller must be a claimer (for request) or an approver (for approve / reject / change) of the category. The original requester is preserved across approve / reject / change transitions.

Request body (optional). Supply a JSON object with a description field to post a companion comment on the task as a side effect of the approval call. Same shape as POST /comment: {"description": "<markdown>", "pinned": false, "asUser": false}. description is required when the body is supplied; pinned and asUser are optional.

The stored comment is a header, a blank line, then the supplied description. The header is a plain <category>: <status> line: the category's name, left out for the default category, then the status in the authorizing user's language (Awaiting approval, Approved, Rejected or Request changes in English). Don't parse it: its wording depends on the language. For example, {"description": "Please tweak the wording."} on a state=change call for the category legal, named Legal Review, stores Legal Review: Request changes\n\nPlease tweak the wording. Don't include the header in description yourself.

Without a body, approve / reject / change still log a comment holding only the header, as the apps do; request logs nothing. The created comment is not included in the response — call GET /comment/list/{taskOid} afterward to fetch it.

To cancel an approval, use DELETE /task/revoke-approval/id/{projectId}/{taskId} (or DELETE /task/revoke-approval/{oid}) — not this endpoint.

Returns 400 Bad Request if ?state= is missing or unknown, or the body has unknown fields, an empty description, or a non-object shape; 403 Forbidden if the caller isn't a claimer / approver; 404 Not Found if the task or ?category= doesn't exist.

Examples:

POST /task/approve/id/my_project/42?category=legal&state=approve
                  (empty body — records the approval and logs a header-only comment)
                  
                  POST /task/approve/id/my_project/42?category=legal&state=change
                  {"description": "Please tweak the wording."}
                  
                  POST /task/approve/iuRRiKoyrxdBFhFTTo?state=request
                  (by OID — requests approval in the default category)
                  
oid: string
in path

Task OID.

state: string request, approve, reject, change
in query

Approval transition to apply: request requests approval (or rolls forward from a decided state back to awaiting); approve / reject / change records the approver's decision.

category: string
in query

(Optional) Approval category ID. Defaults to the project's default category (id "").

return: string full, compact
in query

(Optional) Response shape: full (default) returns the task's approval record; compact returns only the task's {"oid": …, "id": …}. Any other value returns 400 Bad Request.

description: string

Content of the companion comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Required if the body is supplied. The server prepends a <category>: <status> line (status in the authorizing user's language; no category name for the default category) and a blank line before this text, so this field should contain only the human-written message — do not include the header yourself.

pinned: boolean

(Optional) Whether to pin the companion comment on the task. Default: false.

asUser: boolean

(Optional) If true, the comment is attributed to the app rather than the authorizing user ( app-as-user, as the asUser flag on POST /comment). Default: false. Either way, the authorizing user, not the app, follows the task, as for any comment.

Request Example
{
  "description": "Please tweak the wording.",
  "pinned": false,
  "asUser": false
}
200 OK

successful operation

Response Content-Types: application/json
Response Example (200 OK)
{
  "toggledAt": "2026-04-24T10:05:00.000Z",
  "requester": "string",
  "requesterRef": {
    "id": "my_id",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "approverRef": "#/definitions/SimpleEntityWithId",
  "category": "legal",
  "approver": "string",
  "state": "awaiting"
}

Upload an attachment to a task by ID.

POST /task/attach/id/{projectId}/{taskId}/{filename}

Uploads an attachment to an existing task. The request body is the raw file content.

Executable files (.exe, .com, .bat) are rejected unless the project has enabled uploading executable files.

A file over the plan's per-file size limit, or one that would take the organization past its storage quota, is rejected with 402 (code 469).

projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Task ID.

filename: string
in path

Attachment file name, e.g., readme.txt.

Percent-encode it, e.g., My%20Report.pdf for My Report.pdf. It can't contain / or \.

Provide a meaningful extension so the browser can recognize the MIME type (e.g., revenue.pdf, contacts.json).

Alternatively, set the MIME type via the Content-Type header.

Request Example
"object"

OK — newly created attachment.

400 Bad Request

Bad Request — filename or payload invalid, or an executable file is not allowed for this project.

402 Payment Required

Payment Required (code 469) — the file is over the plan's per-file size limit, or the storage quota is used up.

403 Forbidden

Forbidden — caller lacks permission to attach to this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
  "length": 20000,
  "name": "file.txt"
}

Upload an attachment to a task by OID.

POST /task/attach/{taskOid}/{filename}

Uploads an attachment to an existing task. The request body is the raw file content.

Executable files (.exe, .com, .bat) are rejected unless the project has enabled uploading executable files.

A file over the plan's per-file size limit, or one that would take the organization past its storage quota, is rejected with 402 (code 469).

taskOid: string
in path

Task OID.

filename: string
in path

Attachment file name, e.g., readme.txt.

Percent-encode it, e.g., My%20Report.pdf for My Report.pdf. It can't contain / or \.

Provide a meaningful extension so the browser can recognize the MIME type (e.g., revenue.pdf, contacts.json).

Alternatively, set the MIME type via the Content-Type header.

Request Example
"object"

OK — newly created attachment.

400 Bad Request

Bad Request — filename or payload invalid, or an executable file is not allowed for this project.

402 Payment Required

Payment Required (code 469) — the file is over the plan's per-file size limit, or the storage quota is used up.

403 Forbidden

Forbidden — caller lacks permission to attach to this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
  "length": 20000,
  "name": "file.txt"
}

Bulk-add N root tasks to a project by ID.

POST /task/bulk-add/id/{projectId}

Creates up to 300 root tasks in one transaction.

Example: POST /task/bulk-add/id/my_project?return=compact

Body is a top-level JSON array of CreateTaskBody items (no envelope) — same shape as single-task POST /task/.... Items can include nested tasks to create subtrees in the same call; only the root of each item is echoed in the response (use GET /task/list/id/{projectId}/{rootId} to enumerate the created subtree).

Example request body:

[
  {
    "name": "Design new logo",
    "priority": 2,
    "tags": ["design"],
    "assignees": ["me"]
  },
  { "name": "Write spec", "due": "2026-05-10" },
  { "name": "Review" }
]

Example response (full mode, abbreviated):

[
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 42, "name": "Design new logo", "priority": {"value": 2, "name": "Urgent"} },
  { "oid": "abcXyzPqRs",        "id": 43, "name": "Write spec" },
  { "oid": "defLmnQrSt",        "id": 44, "name": "Review" }
]

With ?return=compact, each element is just {oid, id}.

Submitted order is preserved, whatever ?position=: given [A, B, C], the tasks end up as A, B, C from top to bottom.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Example error:

{ "code": 400, "message": "items[1]: Invalid value for `priority`: 99 (expected -1, 0, 1, or 2 (or one of Low/Medium/High/Urgent))" }

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Caveat — returned identifiers are not stable: the oid and id values in a dry-run response are discarded along with everything else. A follow-up real call allocates fresh identifiers, so don't persist or reference dry-run OIDs / IDs across calls.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it. Nested tasks count as items too, for both the cost and the batch size.

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  {
    "description": "This is a *cool* task.",
    "tasks": [
      "#/definitions/CreateTaskBody"
    ],
    "tags": [
      "X6nmx9XjEO2wKbqeB1pRT43C"
    ],
    "partner": "UI design team",
    "assignees": [
      "6QMKkEPBVWETLWrXqws94ALU"
    ],
    "start": "2026-05-01",
    "due": "2026-05-10T17:00Z",
    "recurrence": {
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "asUser": true,
    "followers": [
      "tzufRLqCnud74dARyDSvjWDl"
    ],
    "successors": "[\"#13\"]",
    "yourField": "object",
    "name": "Design new **logo**",
    "status": 0,
    "etc": 0,
    "priority": 0,
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
  }
]
200 OK

OK — array of created tasks (one per submitted item, root only for nested subtrees).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, or any per-item validation failure (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch would exceed the plan's task limit, or holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission to add tasks to the project.

404 Not Found

Not Found — project does not exist.

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-add N tasks relative to a task by ID.

POST /task/bulk-add/id/{projectId}/{taskId}

Creates up to 300 tasks anchored at the task identified by projectId + taskId. The optional ?position= query parameter mirrors single-task POST /task/... semantics:

  • parent (default): children of the anchor task.
  • before: siblings immediately before the anchor.
  • after: siblings immediately after the anchor.

Example: POST /task/bulk-add/id/my_project/42?position=after&return=compact

Request body:

[
  { "name": "Subtask 1" },
  { "name": "Subtask 2" },
  { "name": "Subtask 3" }
]

Response (compact mode):

[
  { "oid": "abc1", "id": 100 },
  { "oid": "abc2", "id": 101 },
  { "oid": "abc3", "id": 102 }
]

All three become siblings of task 42, in submitted order, immediately after task 42.

Body is a top-level JSON array of CreateTaskBody items (no envelope) — same shape as single-task POST /task/.... Items can include nested tasks to create subtrees in the same call; only the root of each item is echoed in the response (use GET /task/list/id/{projectId}/{rootId} to enumerate the created subtree).

Example request body:

[
  {
    "name": "Design new logo",
    "priority": 2,
    "tags": ["design"],
    "assignees": ["me"]
  },
  { "name": "Write spec", "due": "2026-05-10" },
  { "name": "Review" }
]

Example response (full mode, abbreviated):

[
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 42, "name": "Design new logo", "priority": {"value": 2, "name": "Urgent"} },
  { "oid": "abcXyzPqRs",        "id": 43, "name": "Write spec" },
  { "oid": "defLmnQrSt",        "id": 44, "name": "Review" }
]

With ?return=compact, each element is just {oid, id}.

Submitted order is preserved, whatever ?position=: given [A, B, C], the tasks end up as A, B, C from top to bottom.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Example error:

{ "code": 400, "message": "items[1]: Invalid value for `priority`: 99 (expected -1, 0, 1, or 2 (or one of Low/Medium/High/Urgent))" }

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Caveat — returned identifiers are not stable: the oid and id values in a dry-run response are discarded along with everything else. A follow-up real call allocates fresh identifiers, so don't persist or reference dry-run OIDs / IDs across calls.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it. Nested tasks count as items too, for both the cost and the batch size.

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

taskId: integer
in path

Anchor task ID.

position: string parent, before, after
in query

(Optional) Placement of the new tasks relative to the anchor task: parent (default) makes them its children; before / after make them its siblings, immediately before / after it. Any other value returns 400 Bad Request.

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  {
    "description": "This is a *cool* task.",
    "tasks": [
      "#/definitions/CreateTaskBody"
    ],
    "tags": [
      "X6nmx9XjEO2wKbqeB1pRT43C"
    ],
    "partner": "UI design team",
    "assignees": [
      "6QMKkEPBVWETLWrXqws94ALU"
    ],
    "start": "2026-05-01",
    "due": "2026-05-10T17:00Z",
    "recurrence": {
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "asUser": true,
    "followers": [
      "tzufRLqCnud74dARyDSvjWDl"
    ],
    "successors": "[\"#13\"]",
    "yourField": "object",
    "name": "Design new **logo**",
    "status": 0,
    "etc": 0,
    "priority": 0,
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
  }
]
200 OK

OK — array of created tasks (one per submitted item, root only for nested subtrees).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, invalid ?position=, or any per-item validation failure (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch would exceed the plan's task limit, or holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission to add tasks here.

404 Not Found

Not Found — project or anchor task does not exist.

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-add N tasks by OID (project or task anchor).

POST /task/bulk-add/{oid}

Creates up to 300 tasks anchored at the entity identified by oid — a project OID creates root tasks, a task OID creates subtasks (or siblings, depending on ?position=).

Examples: POST /task/bulk-add/0Mg3VQ8kWeiVbLH1PrjzUc89?return=compact adds root tasks to that project; POST /task/bulk-add/iuRRiKoyrxdBFhFTTo?position=after&return=compact adds them right after that task, in submitted order.

Body is a top-level JSON array of CreateTaskBody items (no envelope) — same shape as single-task POST /task/.... Items can include nested tasks to create subtrees in the same call; only the root of each item is echoed in the response (use GET /task/list/id/{projectId}/{rootId} to enumerate the created subtree).

Example request body:

[
  {
    "name": "Design new logo",
    "priority": 2,
    "tags": ["design"],
    "assignees": ["me"]
  },
  { "name": "Write spec", "due": "2026-05-10" },
  { "name": "Review" }
]

Example response (full mode, abbreviated):

[
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 42, "name": "Design new logo", "priority": {"value": 2, "name": "Urgent"} },
  { "oid": "abcXyzPqRs",        "id": 43, "name": "Write spec" },
  { "oid": "defLmnQrSt",        "id": 44, "name": "Review" }
]

With ?return=compact, each element is just {oid, id}.

Submitted order is preserved, whatever ?position=: given [A, B, C], the tasks end up as A, B, C from top to bottom.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Example error:

{ "code": 400, "message": "items[1]: Invalid value for `priority`: 99 (expected -1, 0, 1, or 2 (or one of Low/Medium/High/Urgent))" }

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Caveat — returned identifiers are not stable: the oid and id values in a dry-run response are discarded along with everything else. A follow-up real call allocates fresh identifiers, so don't persist or reference dry-run OIDs / IDs across calls.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it. Nested tasks count as items too, for both the cost and the batch size.

oid: string
in path

OID of the project (root tasks) or anchor task (subtasks / siblings, per ?position=). Specify - for your personal tasks (those in My Tasks that belong to no project).

position: string parent, before, after
in query

(Optional) Placement of the new tasks relative to the anchor task: parent (default) makes them its children; before / after make them its siblings, immediately before / after it. Any other value returns 400 Bad Request. With a project OID, only parent applies; before / after are rejected with 400.

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  {
    "description": "This is a *cool* task.",
    "tasks": [
      "#/definitions/CreateTaskBody"
    ],
    "tags": [
      "X6nmx9XjEO2wKbqeB1pRT43C"
    ],
    "partner": "UI design team",
    "assignees": [
      "6QMKkEPBVWETLWrXqws94ALU"
    ],
    "start": "2026-05-01",
    "due": "2026-05-10T17:00Z",
    "recurrence": {
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "asUser": true,
    "followers": [
      "tzufRLqCnud74dARyDSvjWDl"
    ],
    "successors": "[\"#13\"]",
    "yourField": "object",
    "name": "Design new **logo**",
    "status": 0,
    "etc": 0,
    "priority": 0,
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
  }
]
200 OK

OK — array of created tasks (one per submitted item, root only for nested subtrees).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, invalid ?position= (or before / after with a project OID), or any per-item validation failure (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch would exceed the plan's task limit, or holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission to add tasks here.

404 Not Found

Not Found — anchor does not exist.

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-approve N tasks in a project by ID.

POST /task/bulk-approve/id/{projectId}

Applies a single approval transition (request / approve / reject / change) to all tasks in the batch. Body is a top-level JSON array of task references (OID string, integer ID, or "#<id>" string; mixed forms allowed). Up to 300 items per call; see Batch size below.

Response: one slot per item, in order — the task's full record (with its approval), or {oid, id} with ?return=compact.

Permissions — same per-task role checks as the single-task POST /task/approve/...: the caller must be a claimer (for request) or an approver (for the others) of the category.

Comments — like the single-task endpoint, approve / reject / change log a comment on each task holding only a header; request logs nothing. There is no body field for comment text. The header is a plain <category>: <status> line: the category's name, left out for the default category, then the status in the authorizing user's language (Awaiting approval, Approved, Rejected or Request changes in English). Don't parse it: its wording depends on the language.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. A per-item permission failure is such an error.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

Example:

POST /task/bulk-approve/id/my_project?category=legal&state=approve
Body: [42, "#43", "iuRRiKoyrxdBFhFTTo"]
projectId: string
in path

Project ID.

state: string request, approve, reject, change
in query

Approval transition to apply: request requests approval (or rolls forward from a decided state back to awaiting); approve / reject / change records the approver's decision. Applied to every task in the batch.

category: string
in query

(Optional) Approval category ID. Defaults to the project's default category (id "").

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of updated tasks (same length as the request body; null for skipped items whose task wasn't found).

400 Bad Request

Bad Request — body shape, missing or invalid ?state=, an item that is neither a string nor an integer, or a per-item validation error (with items[i]: prefix).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks claimer / approver role on at least one item (whole batch rolled back).

404 Not Found

Not Found — project or approval ?category= does not exist.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-approve N tasks in a project by OID.

POST /task/bulk-approve/{projectOid}

Applies a single approval transition (request / approve / reject / change) to all tasks in the batch. Body is a top-level JSON array of task references (OID string, integer ID, or "#<id>" string; mixed forms allowed). Up to 300 items per call; see Batch size below.

Response: one slot per item, in order — the task's full record (with its approval), or {oid, id} with ?return=compact.

Permissions — same per-task role checks as the single-task POST /task/approve/...: the caller must be a claimer (for request) or an approver (for the others) of the category.

Comments — like the single-task endpoint, approve / reject / change log a comment on each task holding only a header; request logs nothing. There is no body field for comment text. The header is a plain <category>: <status> line: the category's name, left out for the default category, then the status in the authorizing user's language (Awaiting approval, Approved, Rejected or Request changes in English). Don't parse it: its wording depends on the language.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. A per-item permission failure is such an error.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

Example:

POST /task/bulk-approve/0Mg3VQ8kWeiVbLH1PrjzUc89?category=legal&state=approve
Body: [42, "#43", "iuRRiKoyrxdBFhFTTo"]
projectOid: string
in path

Project OID.

state: string request, approve, reject, change
in query

Approval transition to apply: request requests approval (or rolls forward from a decided state back to awaiting); approve / reject / change records the approver's decision. Applied to every task in the batch.

category: string
in query

(Optional) Approval category ID. Defaults to the project's default category (id "").

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of updated tasks (same length as the request body; null for skipped items whose task wasn't found).

400 Bad Request

Bad Request — body shape, missing or invalid ?state=, an item that is neither a string nor an integer, or a per-item validation error (with items[i]: prefix).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks claimer / approver role on at least one item (whole batch rolled back).

404 Not Found

Not Found — project or approval ?category= does not exist.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Add a new root task.

POST /task/id/{projectId}

Adds a new root task to a project.

Minimal request body only needs name. A fuller example:

{
  "name": "Design new logo",
  "description": "Needs to match the brand guide.",
  "priority": 2,
  "tags": ["design", "urgent"],
  "assignees": ["me"],
  "start": "2026-05-01",
  "due": "2026-05-10",
  "Priority": 3,
  "Owners": ["alice@example.com"]
}

Priority / Owners in this example are custom-field keys from the project's own /project/add-field definitions — they are not fixed API fields and are only recognised by name. See CreateTaskBody.yourField for the rules on each custom-field type.

Tags must exist already, as tags of the project or global tags of its organization; an unknown tag is rejected with 400, not created.

Nested tasks: subtasks created in the same call. Each one costs 1 rate-limit unit, like a separate call, and a call creates at most 300 tasks, nested ones included, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). Over the plan's cap is rejected with 402 (code 469), over 300 with 400; split it.

projectId: string
in path

ID of the project to which this new task will be added. The task will be created as a root task. Specify "-" to add it to personal tasks (in My Tasks).

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) A description of the task. An embedded data: image is rejected — upload the image as an attachment instead.

tasks: CreateTaskBody

(Optional) List of subtasks to create along with this task. Each one, at any depth, costs 1 rate-limit unit and counts toward the per-call cap of 300 tasks and the plan's per-minute limit; see Rate Limits.

tags: string[]

(Optional) A list of tag OIDs or names to be added to the new task. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, such as null, is rejected with 400.

assignees: string[]

(Optional) A list of user identifiers (OID, ID, or email) to assign this task to.

  • Use "me" to indicate the current user.
  • Use "inherit" to include all assignees of the parent task.

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
recurrence: Recurrence

(Optional) Makes the task repeat. Omit it for a task that doesn't repeat.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely.
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Cancel previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

Default: false.

section: boolean

(Optional) Whether this task is a section. Default: false.

milestone: boolean

(Optional) Whether this task is a milestone. Default: false.

asUser: boolean

(Optional) If true, marks this task as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). In bulk-add, each item has its own. A nested task's asUser must match its top-level task's (a tree is created by one author); otherwise the call is rejected with 400.

followers: string[]

(Optional) List of user identifiers (OID, ID, or email) who follow this task. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

  • Use "me" for the current user.
  • Use "inherit" to include followers of the parent task.
  • Use "app" for the application itself to follow (receive notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).
successors: string[]

(Optional) List of successor task identifiers (OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted).
  • Multi-value (fields configured with multiple: true): provide a list.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

The name of the task.

status: integer

(Optional) Task status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Default: 0.

etc: integer

(Optional) Estimated time to complete, in seconds: an integer from 0 to 864,000,000 (10,000 days). null is the same as leaving it out.

priority: integer -1, 0, 1, 2

(Optional) Task priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.) Default: 0 (Medium).

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
Request Example
{
  "description": "This is a *cool* task.",
  "tasks": [
    "#/definitions/CreateTaskBody"
  ],
  "tags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "partner": "UI design team",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "Design new **logo**",
  "status": 0,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}
200 OK

OK — newly created task.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required (code 469) — the plan's task limit is reached, or the call creates more tasks than the plan allows per call (see Nested tasks).

403 Forbidden

Forbidden — caller lacks permission to add a task to this project.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Add a new task relative to another task.

POST /task/id/{projectId}/{taskId}

Adds a new task under another task, or before or after another task. See POST /task/id/{projectId} for a full request-body example — the body shape is identical.

Nested tasks: subtasks created in the same call. Each one costs 1 rate-limit unit, like a separate call, and a call creates at most 300 tasks, nested ones included, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). Over the plan's cap is rejected with 402 (code 469), over 300 with 400; split it.

projectId: string
in path

ID of the project to which the new task will be added. Specify "-" to add it to personal tasks in My Tasks.

taskId: integer
in path

ID of the referenced task.

position: string parent, before, after
in query

(Optional) Placement of the new task relative to the task referenced by taskId:

  • parent (default): child of the referenced task.
  • before: sibling immediately before the referenced task.
  • after: sibling immediately after the referenced task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) A description of the task. An embedded data: image is rejected — upload the image as an attachment instead.

tasks: CreateTaskBody

(Optional) List of subtasks to create along with this task. Each one, at any depth, costs 1 rate-limit unit and counts toward the per-call cap of 300 tasks and the plan's per-minute limit; see Rate Limits.

tags: string[]

(Optional) A list of tag OIDs or names to be added to the new task. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, such as null, is rejected with 400.

assignees: string[]

(Optional) A list of user identifiers (OID, ID, or email) to assign this task to.

  • Use "me" to indicate the current user.
  • Use "inherit" to include all assignees of the parent task.

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
recurrence: Recurrence

(Optional) Makes the task repeat. Omit it for a task that doesn't repeat.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely.
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Cancel previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

Default: false.

section: boolean

(Optional) Whether this task is a section. Default: false.

milestone: boolean

(Optional) Whether this task is a milestone. Default: false.

asUser: boolean

(Optional) If true, marks this task as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). In bulk-add, each item has its own. A nested task's asUser must match its top-level task's (a tree is created by one author); otherwise the call is rejected with 400.

followers: string[]

(Optional) List of user identifiers (OID, ID, or email) who follow this task. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

  • Use "me" for the current user.
  • Use "inherit" to include followers of the parent task.
  • Use "app" for the application itself to follow (receive notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).
successors: string[]

(Optional) List of successor task identifiers (OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted).
  • Multi-value (fields configured with multiple: true): provide a list.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

The name of the task.

status: integer

(Optional) Task status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Default: 0.

etc: integer

(Optional) Estimated time to complete, in seconds: an integer from 0 to 864,000,000 (10,000 days). null is the same as leaving it out.

priority: integer -1, 0, 1, 2

(Optional) Task priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.) Default: 0 (Medium).

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
Request Example
{
  "description": "This is a *cool* task.",
  "tasks": [
    "#/definitions/CreateTaskBody"
  ],
  "tags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "partner": "UI design team",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "Design new **logo**",
  "status": 0,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}
200 OK

OK — newly created task.

400 Bad Request

Bad Request — body validation failed.

402 Payment Required

Payment Required (code 469) — the plan's task limit is reached, or the call creates more tasks than the plan allows per call (see Nested tasks).

403 Forbidden

Forbidden — caller lacks permission to add a task here.

404 Not Found

Not Found — project or parent task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Add a new root task, or relative to another task.

POST /task/{oid}

Adds a new task to a project, under another task, or before or after another task.

Nested tasks: subtasks created in the same call. Each one costs 1 rate-limit unit, like a separate call, and a call creates at most 300 tasks, nested ones included, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). Over the plan's cap is rejected with 402 (code 469), over 300 with 400; split it.

oid: string
in path

OID of the project or task to which the new task will be added. If the OID refers to a project, the new task becomes a root task. If it refers to a task, the new task becomes its subtask. Specify - for your personal tasks (those in My Tasks that belong to no project).

position: string parent, before, after
in query

(Optional) Placement of the new task relative to the task referenced by oid:

  • parent (default): child of the referenced task.
  • before: sibling immediately before the referenced task.
  • after: sibling immediately after the referenced task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request, and so do before / after when oid refers to a project.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) A description of the task. An embedded data: image is rejected — upload the image as an attachment instead.

tasks: CreateTaskBody

(Optional) List of subtasks to create along with this task. Each one, at any depth, costs 1 rate-limit unit and counts toward the per-call cap of 300 tasks and the plan's per-minute limit; see Rate Limits.

tags: string[]

(Optional) A list of tag OIDs or names to be added to the new task. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, such as null, is rejected with 400.

assignees: string[]

(Optional) A list of user identifiers (OID, ID, or email) to assign this task to.

  • Use "me" to indicate the current user.
  • Use "inherit" to include all assignees of the parent task.

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
recurrence: Recurrence

(Optional) Makes the task repeat. Omit it for a task that doesn't repeat.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely.
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Cancel previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

Default: false.

section: boolean

(Optional) Whether this task is a section. Default: false.

milestone: boolean

(Optional) Whether this task is a milestone. Default: false.

asUser: boolean

(Optional) If true, marks this task as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). In bulk-add, each item has its own. A nested task's asUser must match its top-level task's (a tree is created by one author); otherwise the call is rejected with 400.

followers: string[]

(Optional) List of user identifiers (OID, ID, or email) who follow this task. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

  • Use "me" for the current user.
  • Use "inherit" to include followers of the parent task.
  • Use "app" for the application itself to follow (receive notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).
successors: string[]

(Optional) List of successor task identifiers (OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted).
  • Multi-value (fields configured with multiple: true): provide a list.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

The name of the task.

status: integer

(Optional) Task status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Default: 0.

etc: integer

(Optional) Estimated time to complete, in seconds: an integer from 0 to 864,000,000 (10,000 days). null is the same as leaving it out.

priority: integer -1, 0, 1, 2

(Optional) Task priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.) Default: 0 (Medium).

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
Request Example
{
  "description": "This is a *cool* task.",
  "tasks": [
    "#/definitions/CreateTaskBody"
  ],
  "tags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "partner": "UI design team",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "Design new **logo**",
  "status": 0,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}
200 OK

OK — newly created task.

400 Bad Request

Bad Request — body validation failed, or position is before / after while oid is a project.

402 Payment Required

Payment Required (code 469) — the plan's task limit is reached, or the call creates more tasks than the plan allows per call (see Nested tasks).

403 Forbidden

Forbidden — caller lacks permission to add a task here.

404 Not Found

Not Found — project or parent task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Search tasks in a folder by folder ID.

GET /task/search-folder/id/{folderId}

Returns tasks that match the specified criteria in the given folder, most recently edited first (best match first with text). Tasks in archived projects are excluded. Pass at least one query parameter; none is rejected with 400. Custom-field filters and sublist aren't supported here (400); search a project for those.

Available for Professional plans and above; on the Free plan it is rejected with 402 (code 469).

Pagination: a page holds up to ?limit= tasks (30 by default). When more matches remain, the page's last item carries a cursor; pass it back as ?cursor= with the same ?limit= and filters for the next page, until a page's last item has none. The token is opaque — use it verbatim. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

folderId: string
in path

Folder ID.

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field.

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a custom field, sublist, or a malformed or too deep cursor).

402 Payment Required

Payment Required (code 469) — the organization is on the Free plan.

403 Forbidden

Forbidden — caller lacks permission to search this folder.

404 Not Found

Not Found — folder does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Search tasks in a folder by folder OID.

GET /task/search-folder/{folderOid}

Returns tasks that match the specified criteria in the given folder, most recently edited first (best match first with text). Tasks in archived projects are excluded. Pass at least one query parameter; none is rejected with 400. Custom-field filters and sublist aren't supported here (400); search a project for those.

Available for Professional plans and above; on the Free plan it is rejected with 402 (code 469).

Pagination: a page holds up to ?limit= tasks (30 by default). When more matches remain, the page's last item carries a cursor; pass it back as ?cursor= with the same ?limit= and filters for the next page, until a page's last item has none. The token is opaque — use it verbatim. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

See also the by-ID form GET /task/search-folder/id/{folderId}.

folderOid: string
in path

Folder OID.

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field.

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a custom field, sublist, or a malformed or too deep cursor).

402 Payment Required

Payment Required (code 469) — the organization is on the Free plan.

403 Forbidden

Forbidden — caller lacks permission to search this folder.

404 Not Found

Not Found — folder does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Search tasks in an organization by organization ID.

GET /task/search-organization/id/{organizationId}

Returns tasks that match the specified criteria in the given organization, most recently edited first (best match first with text). Tasks in archived projects are excluded. Pass at least one query parameter; none is rejected with 400. Custom-field filters and sublist aren't supported here (400); search a project for those.

Available for Professional plans and above; on the Free plan it is rejected with 402 (code 469).

Pagination: a page holds up to ?limit= tasks (30 by default). When more matches remain, the page's last item carries a cursor; pass it back as ?cursor= with the same ?limit= and filters for the next page, until a page's last item has none. The token is opaque — use it verbatim. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

organizationId: string
in path

Organization ID.

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field.

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a custom field, sublist, or a malformed or too deep cursor).

402 Payment Required

Payment Required (code 469) — the organization is on the Free plan.

403 Forbidden

Forbidden — caller lacks permission to search this organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Search tasks in an organization by organization OID.

GET /task/search-organization/{organizationOid}

Returns tasks that match the specified criteria in the given organization, most recently edited first (best match first with text). Tasks in archived projects are excluded. Pass at least one query parameter; none is rejected with 400. Custom-field filters and sublist aren't supported here (400); search a project for those.

Available for Professional plans and above; on the Free plan it is rejected with 402 (code 469).

Pagination: a page holds up to ?limit= tasks (30 by default). When more matches remain, the page's last item carries a cursor; pass it back as ?cursor= with the same ?limit= and filters for the next page, until a page's last item has none. The token is opaque — use it verbatim. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

See also the by-ID form GET /task/search-organization/id/{organizationId}.

organizationOid: string
in path

Organization OID.

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field.

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a custom field, sublist, or a malformed or too deep cursor).

402 Payment Required

Payment Required (code 469) — the organization is on the Free plan.

403 Forbidden

Forbidden — caller lacks permission to search this organization.

404 Not Found

Not Found — organization does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Get an existing task by its ID.

GET /task/id/{projectId}/{taskId}

Returns the full task record.

projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Task ID.

OK — task record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Get an existing task by its OID.

GET /task/{oid}

Returns the full task record.

oid: string
in path

Task OID.

OK — task record.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Get all root tasks of the given project.

GET /task/list/id/{projectId}

Returns all root tasks of the project as a bare JSON array.

Pagination is opt-in via ?limit=N (1..1000). Without ?limit= or ?cursor=, the response is the full bare array. When ?limit=N is set and more results exist, the LAST item carries "cursor": "<token>" — pass it back as ?cursor=<token> (plus the same ?limit= and any filter like ?status=) to fetch the next page. End of stream is signalled by the absence of cursor on the last item. ?limit=no is an explicit "return everything". Same pagination grammar applies to the subtasks endpoint GET /task/list/id/{projectId}/{taskId}.

Pair with ?return=compact to render each item as {oid, id, cursor?} for navigation/lookup workloads at minimal token cost.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned. See Rate Limits.

?depth= isn't available here: only 1, the default, is accepted. To walk a subtree, list a task's subtasks with GET /task/list/id/{projectId}/{taskId}?depth=…. To retrieve all tasks (including all subtasks), use the search API.

projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

status: string
in query

Task status filter. Specify a status value (an integer 0..100; 100 matches every completed status), or use "active" for active tasks or "completed" for completed tasks. Any other value returns 400.

limit: string
in query

Page size (1..1000). Omit for the default unpaginated full list, or pass no to be explicit. When set and more results exist, the last item in the response carries a cursor field.

cursor: string
in query

Continuation token. Pass back the cursor value from the last item of the previous page to fetch the next page. Re-pass any filter (?status=) and ?limit= on the same call.

return: string full, compact
in query

(Optional) Response shape: full (default) for the standard task records, or compact for identifier-only items, {oid, id, cursor?}. Any other value returns 400 Bad Request.

200 OK

OK — bare array of root tasks (may be empty). With ?limit=N, the last item may carry a cursor field if more results exist.

400 Bad Request

Bad Request — invalid ?status= / ?limit= / ?return= value, ?depth= other than 1, or ?cursor= doesn't belong to this list.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Get the subtasks of the given task.

GET /task/list/id/{projectId}/{taskId}

By default returns only the direct subtasks of {taskId} (one level). To fetch a whole subtree in a single call, set ?depth=N or ?depth=full — each task in the response then carries a nested tasks field with its walked children, recursively.

When to use which:

  • Default (no ?depth): you only need the immediate children.
  • ?depth=2 or 3: small subtree where you know the shape.
  • ?depth=full: full subtree snapshot — pair with ?return=compact for navigation/lookup workloads to keep the payload (and LLM-token cost) small.

Per-tier total-nodes cap when ?depth>1: Free → rejected (402), Pro → 500, Premium → 2,000, Enterprise → unlimited (bounded only by the global response-size ceiling). When the cap fires mid-walk, the partial subtree is returned and the last emitted sibling at the cropped level carries "cropped": true. Recovery: list that sibling's parent again without ?depth to fetch the rest of that level — flat single-level lists have no cap.

Tree shape signals for the agent:

  • Node has a tasks array → its children were walked. Empty array means a true leaf.
  • Node has no tasks field → its children were not walked (depth limit reached, or cap fired before reaching it). Drill in if you need them.
  • Node has "cropped": true → more siblings of this node exist at the same level.

?status= with ?depth>1: a task that doesn't match is left out with its whole subtree, so a matching subtask under a non-matching task is not returned. Use the search endpoints to find matches at any depth.

Pagination (flat path only, cannot be combined with ?depth>1): pass ?limit=N (1..1000) to opt into paginated chunks. When more results exist, the LAST item carries "cursor": "<token>" — pass it back as ?cursor=<token> (plus the same ?limit= and ?status=) for the next page. Without ?limit= / ?cursor=, the response is the full bare array. ?limit=no is an explicit "return everything". Composes with ?return=compact.

Notes: Subtree responses (?depth>1) omit the per-task childCount field — the tasks array is the canonical signal. The flat default (?depth=1) and single-task GET /task/{oid} still include childCount. ?depth>1 cannot be combined with ?limit= or ?cursor= (returns 400).

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned. See Rate Limits. With ?depth>1, N counts every task in the returned subtree.

projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Parent task ID.

status: string
in query

Task status filter. Specify a status value (an integer 0..100; 100 matches every completed status), or use "active" for active tasks or "completed" for completed tasks. Any other value returns 400. With ?depth>1, a task that doesn't match is left out with its whole subtree, even subtasks that match.

depth: string
in query

Subtree depth. Omit or 1 for the default flat single-level list (immediate children only). Any positive integer returns a multi-level subtree capped at the given depth; full walks every level (bounded by the per-tier total-nodes cap). ?depth>1 requires the Professional plan or above and cannot be combined with ?limit/?cursor.

limit: string
in query

Page size for the flat path (1..1000). Omit for the default unpaginated full list. Pass no to be explicit. When set and more results exist, the last item in the response carries a cursor field. Cannot be combined with ?depth>1.

cursor: string
in query

Continuation token. Pass back the cursor value from the last item of the previous page to fetch the next page. Re-pass ?limit= and any filter (?status=) on the same call. Cannot be combined with ?depth>1.

return: string full, compact
in query

(Optional) Response shape: full (default) for the standard task records, or compact for identifier-only items, {oid, id, cursor?}. Any other value returns 400 Bad Request. With ?depth>1, a compact item is {oid, id, tasks?, cropped?}. Pair with ?depth=full (subtree) or ?limit=N (paginated) to fetch a whole subtree's / page's identifier graph at minimal token cost; the agent then GET /task/{oid} for only the items it wants in detail.

200 OK

OK — list of subtasks (may be empty). With ?depth>1, each entry may carry nested tasks + cropped fields.

400 Bad Request

Bad Request — invalid ?status= / ?depth= / ?limit= / ?return= value, ?depth>1 combined with ?limit/?cursor, or ?cursor= doesn't belong to this list.

402 Payment Required

Payment Required (code 469) — ?depth>1 requires the Professional plan or above. Use ?depth=1 (or omit ?depth) for unrestricted flat per-level listing.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project or parent task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Get all root tasks of the given project or all subtasks of the given task.

GET /task/list/{oid}

Returns all root tasks of a project or all direct subtasks of a task by OID. If the OID is a project, root tasks are returned. If it is a task, its direct subtasks are returned.

One level is returned by default. When the OID is a task, ?depth=N / ?depth=full walks the subtree in a single call — each task in the response then carries a nested tasks field with its walked children, recursively. ?depth>1 is not available when the OID is a project (there is no parent task to walk from); use the flat list per level instead.

When to use which:

  • Default (no ?depth): you only need the immediate children.
  • ?depth=2 or 3: small subtree where you know the shape.
  • ?depth=full: full subtree snapshot — pair with ?return=compact for navigation/lookup workloads to keep the payload (and LLM-token cost) small.

Per-tier total-nodes cap when ?depth>1: Free → rejected (402), Pro → 500, Premium → 2,000, Enterprise → unlimited (bounded only by the global response-size ceiling). When the cap fires mid-walk, the partial subtree is returned and the last emitted sibling at the cropped level carries "cropped": true. Recovery: list that sibling's parent again without ?depth to fetch the rest of that level — flat single-level lists have no cap.

Tree shape signals for the agent:

  • Node has a tasks array → its children were walked. Empty array means a true leaf.
  • Node has no tasks field → its children were not walked (depth limit reached, or cap fired before reaching it). Drill in if you need them.
  • Node has "cropped": true → more siblings of this node exist at the same level.

?status= with ?depth>1: a task that doesn't match is left out with its whole subtree, so a matching subtask under a non-matching task is not returned. Use the search endpoints to find matches at any depth.

Pagination (flat path only, cannot be combined with ?depth>1): pass ?limit=N (1..1000) to opt into paginated chunks. When more results exist, the LAST item carries "cursor": "<token>" — pass it back as ?cursor=<token> (plus the same ?limit= and ?status=) for the next page. Without ?limit= / ?cursor=, the response is the full bare array. ?limit=no is an explicit "return everything". Composes with ?return=compact.

Notes: Subtree responses (?depth>1) omit the per-task childCount field — the tasks array is the canonical signal. The flat default (?depth=1) and single-task GET /task/{oid} still include childCount. ?depth>1 cannot be combined with ?limit= or ?cursor= (returns 400).

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned. See Rate Limits. With ?depth>1, N counts every task in the returned subtree.

oid: string
in path

OID of the project or parent task. Specify - for your personal tasks (those in My Tasks that belong to no project).

status: string
in query

Task status filter. Specify a status value (an integer 0..100; 100 matches every completed status), or use "active" for active tasks or "completed" for completed tasks. Any other value returns 400. With ?depth>1, a task that doesn't match is left out with its whole subtree, even subtasks that match.

depth: string
in query

Subtree depth, only when the OID is a task. Omit or 1 for the default flat single-level list. Any positive integer returns a multi-level subtree capped at that depth; full walks every level (bounded by the per-tier total-nodes cap). ?depth>1 requires the Professional plan or above and cannot be combined with ?limit/?cursor.

limit: string
in query

Page size (1..1000). Omit for the default unpaginated full list, or pass no to be explicit. When set and more results exist, the last item in the response carries a cursor field.

cursor: string
in query

Continuation token. Pass back the cursor value from the last item of the previous page to fetch the next page. Re-pass any filter (?status=) and ?limit= on the same call.

return: string full, compact
in query

(Optional) Response shape: full (default) for the standard task records, or compact for identifier-only items, {oid, id, cursor?}. Any other value returns 400 Bad Request. With ?depth>1, a compact item is {oid, id, tasks?, cropped?}.

200 OK

OK — list of tasks (may be empty).

400 Bad Request

Bad Request — invalid ?status= / ?depth= / ?limit= / ?return= value, ?depth>1 when the OID is a project, ?depth>1 combined with ?limit/?cursor, or ?cursor= doesn't belong to this list.

402 Payment Required

Payment Required (code 469) — ?depth>1 requires the Professional plan or above.

403 Forbidden

Forbidden — the user can't access it, or didn't authorize it for this app.

404 Not Found

Not Found — project or parent task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Search tasks in a project by project ID.

GET /task/search/id/{projectId}

Returns tasks that match the specified criteria in the project, most recently edited first (best match first with text). Pass at least one query parameter; none is rejected with 400.

Custom Field Filtering

You can filter by custom fields by passing the field name as a query parameter (case-insensitive). For example, ?cost=13 or ?approvedBy=john.doe. A field you can't view is an unknown query parameter.

Supported field types and value formats:

Operator grammar — Number, Money, Duration, and Date fields share a common set of operators (case-insensitive): ge:<v>, gt:<v>, le:<v>, lt:<v>, eq:<v>, ne:<v>, between:<v1>,<v2> (inclusive on both ends), notBetween:<v1>,<v2>, and isNull / isNotNull. Number, Money, and Duration also accept a bare value as an exact match (same as eq:). Date instead accepts keyword ops (today, past, last7d, ...) and requires an operator or keyword — a bare date is not accepted. The <v> operand format per type is below.

Type Value format Example
Number, Money <v> is a number cost=13, cost=ge:100, cost=between:50,150, cost=isNull
Checkbox true or false done=true
Select Option name stage=Review
User User ID, email, or OID approvedBy=john.doe
Task Task ID (integer) or OID blockedBy=42
Email, Hyperlink Exact value, or prefix with ~ for regex, ~* for case-insensitive regex website=~example\.com
Duration <v> is <n> seconds, or <n> with suffix d (days) / h (hours) / m (minutes) estimate=2h, estimate=ge:2h, estimate=between:8h,40h, estimate=isNull
Date <v> is YYYY-MM-DD or ISO 8601 YYYY-MM-DDTHH:MM:SSZ (a timestamp operand requires a withTime: true field). Same grammar as the start / due query params. approvedAt=today, approvedAt=ge:2026-04-01, approvedAt=between:2026-04-01,2026-04-30, approvedAt=isNull

Not supported: Text (use text for full-text search instead), Formula, File, Lookup.

A query parameter spelled exactly like a built-in one, e.g. priority, is the built-in filter, even if a custom field has that name.

Pagination

A page holds up to ?limit=N tasks (30 by default). When more matches remain, the last item carries a cursor field; pass its value back as ?cursor=<token> (along with the same ?limit= and any filter) to fetch the next page. End of stream is signalled by the absence of cursor on the last item.

Example loop:

GET /task/search/id/my_project?status=active&limit=30
    → 30 items; last has cursor: "crsr1u"
GET /task/search/id/my_project?status=active&limit=30&cursor=crsr1u
    → 30 items; last has cursor: "crsr11k"
GET /task/search/id/my_project?status=active&limit=30&cursor=crsr11k
    → 12 items; no cursor on last item → stop

With ?sublist=, no item carries a cursor: pass a limit big enough (or no) to get every match. Passing ?cursor= with it is rejected with 400. The cursor token is opaque — use it verbatim from the previous response. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

projectId: string
in path

ID of the task's project. Specify - for your personal tasks (those in My Tasks that belong to no project).

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

sublist: string
in query

Return only tasks in this sublist, by its ID or OID. No item then carries a cursor: pass a limit big enough (or no) to get every match.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep. Cannot be combined with ?sublist=.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field (never with ?sublist=).

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a malformed or too deep cursor, or ?cursor= with ?sublist=).

402 Payment Required

Payment Required (code 469) — on the Free plan, limit is over 30 or no.

403 Forbidden

Forbidden — caller lacks permission to search this project.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Search tasks in a project by project OID.

GET /task/search/{projectOid}

Returns tasks that match the specified criteria in the project, most recently edited first (best match first with text). Pass at least one query parameter; none is rejected with 400.

Custom Field Filtering

You can filter by custom fields by passing the field name as a query parameter (case-insensitive). For example, ?cost=13 or ?approvedBy=john.doe. A field you can't view is an unknown query parameter.

Supported field types and value formats:

Operator grammar — Number, Money, Duration, and Date fields share a common set of operators (case-insensitive): ge:<v>, gt:<v>, le:<v>, lt:<v>, eq:<v>, ne:<v>, between:<v1>,<v2> (inclusive on both ends), notBetween:<v1>,<v2>, and isNull / isNotNull. Number, Money, and Duration also accept a bare value as an exact match (same as eq:). Date instead accepts keyword ops (today, past, last7d, ...) and requires an operator or keyword — a bare date is not accepted. The <v> operand format per type is below.

Type Value format Example
Number, Money <v> is a number cost=13, cost=ge:100, cost=between:50,150, cost=isNull
Checkbox true or false done=true
Select Option name stage=Review
User User ID, email, or OID approvedBy=john.doe
Task Task ID (integer) or OID blockedBy=42
Email, Hyperlink Exact value, or prefix with ~ for regex, ~* for case-insensitive regex website=~example\.com
Duration <v> is <n> seconds, or <n> with suffix d (days) / h (hours) / m (minutes) estimate=2h, estimate=ge:2h, estimate=between:8h,40h, estimate=isNull
Date <v> is YYYY-MM-DD or ISO 8601 YYYY-MM-DDTHH:MM:SSZ (a timestamp operand requires a withTime: true field). Same grammar as the start / due query params. approvedAt=today, approvedAt=ge:2026-04-01, approvedAt=between:2026-04-01,2026-04-30, approvedAt=isNull

Not supported: Text (use text for full-text search instead), Formula, File, Lookup.

A query parameter spelled exactly like a built-in one, e.g. priority, is the built-in filter, even if a custom field has that name.

Pagination

A page holds up to ?limit=N tasks (30 by default). When more matches remain, the last item carries a cursor field; pass its value back as ?cursor=<token> (along with the same ?limit= and any filter) to fetch the next page. End of stream is signalled by the absence of cursor on the last item.

Example loop:

GET /task/search/id/my_project?status=active&limit=30
    → 30 items; last has cursor: "crsr1u"
GET /task/search/id/my_project?status=active&limit=30&cursor=crsr1u
    → 30 items; last has cursor: "crsr11k"
GET /task/search/id/my_project?status=active&limit=30&cursor=crsr11k
    → 12 items; no cursor on last item → stop

With ?sublist=, no item carries a cursor: pass a limit big enough (or no) to get every match. Passing ?cursor= with it is rejected with 400. The cursor token is opaque — use it verbatim from the previous response. Paging reaches at most 1,000,000 rows deep; a deeper cursor is rejected with 400 — narrow the search with filters instead.

Rate-limit cost: max(1, ceil(N / 100)) units, where N is the number of tasks returned — e.g. 1 for a page of 100 or fewer, 10 for 1,000. See Rate Limits.

See also the by-ID form GET /task/search/id/{projectId}.

projectOid: string
in path

Project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

text: string
in query

Full-text query against task name, description, attachments, and the values of the custom fields you can view. At most 256 characters. Note: does not include comment content or comment attachments. Indexing can take ~10 seconds or more after updates.

name: string
in query

Task name filter, matched against the name's Markdown source. A bare value matches the whole name exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters. Use text for full-text search.

description: string
in query

Task description filter, matched against the description's Markdown source. A bare value matches the whole description exactly (case-sensitive). Prefix with ~ for a regex, ~* for a case-insensitive regex; an invalid regex is rejected with 400. At most 256 characters.

sublist: string
in query

Return only tasks in this sublist, by its ID or OID. No item then carries a cursor: pass a limit big enough (or no) to get every match.

status: string
in query

Task status filter: active (not completed), completed, or an integer 0..100 for that status, where 100 matches every completed status, like completed. Any other value returns 400.

scheduled: boolean
in query

Return only scheduled tasks (start or due is set). If scheduled=false, returns only tasks where neither start nor due is set.

mine: boolean
in query

Return only "My Tasks" (assigned to me, or created by me and scheduled but unassigned).

assignee: string
in query

Filter by assignee. Each value is a user OID, user ID, or email.

Combine values with , (AND), | (OR), and ! (NOT). AND binds tighter than OR.

Examples:

  • alice — a single user (by ID)
  • alice@example.com — by email
  • alice,bob — assigned to both
  • alice|bob — assigned to either
  • alice,!bob — assigned to alice but not bob
  • alice,bob|carol — (alice AND bob) OR carol
assignor: string
in query

Filter by assignor (the user who set the assignment). Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

follower: string
in query

Filter by follower. Each value is a user OID, user ID, or email. Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Examples: alice, alice,!bob, alice|bob.

tag: string
in query

Filter by tag. Each value is a tag OID or a tag name (case-sensitive). In a project search, a name matches the project's tags and its organization's global tags; in an organization or folder search, any tag in the organization.

Combine with , (AND), | (OR), ! (NOT); AND binds tighter than OR.

Names containing ,, |, !, ", or whitespace must be wrapped in "...". Inside quotes, write \" for a literal " and \\ for a literal \; any other \x is preserved as two literal characters.

Examples:

  • Legal — a single tag
  • Legal,!Draft — has Legal but not Draft
  • "In Progress",!Done — quoted name with space
  • "Foo\"s Go"|Other — quoted with escaped "
modified: string
in query

Return only tasks created or modified within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

commented: string
in query

Return only tasks commented on within the given period: a number of days (7), or a number with the suffix d (days), h (hours), or m (minutes), e.g. 8h. An empty value means 7 days; false turns the filter off.

source-ref: string
in query

Return only tasks whose sourceRef has this key, whatever its value: github finds the tasks created with "sourceRef": {"github": {"repo": "acme/web", "issue": 42}}. sourceRef is a JSON object an app stores when it creates or updates a task: its own data under a key named after the app, plus an optional text that Quire shows as the task's source line. This parameter's former name, sourceRef, still works.

created: string
in query

Filter by the task's createdAt timestamp. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<timestamp> or {between|notBetween}:<timestamp>,<timestamp>
  • <timestamp> is ISO 8601 YYYY-MM-DDTHH:MM:SSZ (UTC); a date-only operand such as 2026-04-01 is rejected with 400
  • isNull / isNotNull are rejected with 400, since createdAt is never null
  • Day boundaries resolve in the caller's timezone; week start follows the caller's locale
  • past on this field is < now()
  • Tokens and keywords are case-insensitive

Examples: today, last7d, ge:2026-04-01T00:00:00Z, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

edited: string
in query

Filter by the task's editedAt timestamp. Same grammar as created, timestamps only, and isNull / isNotNull are rejected with 400. Note: editedAt is NULL for tasks that have never been edited after creation; such tasks are excluded by every op (use created to filter by creation time).

Examples: today, last7d, ge:2026-04-01T00:00:00Z.

archived: string
in query

Filter by the task's archivedAt timestamp. Same grammar as created (timestamps only), plus null ops since the field is nullable:

  • isNull — not archived
  • isNotNull — archived (any time)

Examples: isNotNull, today, ge:2026-04-01T00:00:00Z.

unarchived: string
in query

Filter by the task's reshowAt timestamp (scheduled un-archive). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: isNotNull, today, between:2026-04-01T00:00:00Z,2026-04-30T23:59:59Z.

toggled: string
in query

Filter by the task's toggledAt timestamp (when its completion status was last changed). Same grammar as archived (timestamps only; supports isNull / isNotNull).

Examples: today, isNotNull, ge:2026-04-01T00:00:00Z.

start: string
in query

Filter by the task's start date/time. Value grammar:

  • Keyword: past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek
  • Value op: {ge|gt|le|lt|eq|ne}:<value> or {between|notBetween}:<value>,<value>
  • Null op: isNull, isNotNull
  • <value> is either a date (YYYY-MM-DD) or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ)
  • A date operand expands to a whole-day window in the caller's timezone (ge:2026-04-01 means "on or after Apr 1 in the caller's calendar"); gt:D/le:D use end-of-day, lt:D/ge:D use start-of-day
  • past on start/due is < today 00:00 in the caller's timezone (not < now())
  • upcoming on start/due is the window [tomorrow, today + 7 days)

Examples: today, upcoming, ge:2026-04-01, between:2026-04-01,2026-04-30, isNull.

due: string
in query

Filter by the task's due date/time. Same grammar and semantics as start (accepts date-only operands, isNull/isNotNull, and the same keyword/value ops).

Examples: today, upcoming, le:2026-04-30, isNotNull.

priority: string
in query

Filter by task priority. Each value is an integer (-1..2) or a label (low, medium, high, urgent; case-insensitive): -1 Low, 0 Medium, 1 High, 2 Urgent. Any other value, such as none, is rejected with 400.

Combine with , (AND), | (OR), ! (NOT). AND of two distinct positives is the empty set (a task has exactly one priority); negation works as expected.

Examples: high, 1, high|urgent, !low.

type: string
in query

Filter by task type. Values: normal (or task), section, milestone. Combine with , / | / !. Useful for structural navigation (e.g., listing only sections in a project).

Examples: section, section|milestone, !section.

created-by: string
in query

Filter by the user who created the task. Each value is a user OID, user ID, or email. Combine with , / | / ! (same grammar as assignee). This parameter's former name, createdBy, still works.

Examples: alice, alice|bob, !alice.

recurring: string
in query

Filter on whether the task has a recurrence configured. true (or empty) returns only recurring tasks; false returns only non-recurring tasks. Any other value returns 400 Bad Request.

limit: string
in query

Maximum number of tasks per page. Default: 30. Use no to return all matches.

On the Free plan, a limit over 30, or no, is rejected with 402 (code 469).

cursor: string
in query

Continuation token from the previous page's last item. See Pagination in the operation notes for the loop. At most 1,000,000 rows deep. Cannot be combined with ?sublist=.

OK — matching tasks (may be empty). When more matches remain, the last item carries a cursor field (never with ?sublist=).

400 Bad Request

Bad Request — no query parameter, or an invalid or unknown one (incl. a malformed or too deep cursor, or ?cursor= with ?sublist=).

402 Payment Required

Payment Required (code 469) — on the Free plan, limit is over 30 or no.

403 Forbidden

Forbidden — caller lacks permission to search this project.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]

Bulk-move N tasks within a project by ID.

PUT /task/bulk-move/id/{projectId}

Example: PUT /task/bulk-move/id/my_project?task=99&return=compact

Repositions up to 300 tasks (with their subtasks) within a project to the same destination anchor in one transaction. Same query-param grammar as single-task PUT /task/move/...:

  • ?task=root — move items to project root (only valid with default ?position=parent).
  • ?task={ref}&position=parent (default) — items become children of the reference task.
  • ?task={ref}&position=before — items become siblings immediately before the reference.
  • ?task={ref}&position=after — items become siblings immediately after the reference.

{ref} follows the URL grammar (same as single-task move): the by-ID URL form expects an integer task ID (or root); the by-OID form expects a task OID. A {ref} that isn't found, or is in another project, is rejected with 400. Items in the body use the bulk mixed-form convention (OID / integer ID / #<id> string) — same as bulk-remove.

Request body (mixed-form refs):

[ 42, "#17", "iuRRiKoyrxdBFhFTTo" ]

Response (compact mode; slot 1 was already removed by another caller, so it's null):

[
  { "oid": "abc1Foo", "id": 42 },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 88 }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Moving a task under one of its own subtasks is such an error (400).

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. An item in another project is skipped too.

Order preservation (sliding chain): items are moved in submitted order. Items 1..N-1 are positioned after the previous successful move, regardless of the URL ?position= — without this, ?position=after R would reverse the batch.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

All items must belong to the project in the URL. Cross-project moves go through bulk-transfer.

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

Reference task ID (the destination anchor for the whole batch), or root to move items to the project root.

position: string parent, before, after
in query

(Optional) Placement of moved items relative to the reference: parent (default), before, or after. before / after require ?task= to refer to a task (not root).

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of moved tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error, ?task= missing, not found, or in another project, invalid ?position=, ?task=root&position=before|after, or an item moved under its own subtask. Whole batch rolled back.

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

404 Not Found

Not Found — project does not exist. (Item-level not-found is silent skip.)

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-move N tasks within a project by OID.

PUT /task/bulk-move/{projectOid}

Example: PUT /task/bulk-move/0Mg3VQ8kWeiVbLH1PrjzUc89?task=iuRRiKoyrxdBFhFTTo&return=compact

Repositions up to 300 tasks (with their subtasks) within a project to the same destination anchor in one transaction. Same query-param grammar as single-task PUT /task/move/...:

  • ?task=root — move items to project root (only valid with default ?position=parent).
  • ?task={ref}&position=parent (default) — items become children of the reference task.
  • ?task={ref}&position=before — items become siblings immediately before the reference.
  • ?task={ref}&position=after — items become siblings immediately after the reference.

{ref} follows the URL grammar (same as single-task move): the by-ID URL form expects an integer task ID (or root); the by-OID form expects a task OID. A {ref} that isn't found, or is in another project, is rejected with 400. Items in the body use the bulk mixed-form convention (OID / integer ID / #<id> string) — same as bulk-remove.

Request body (mixed-form refs):

[ 42, "#17", "iuRRiKoyrxdBFhFTTo" ]

Response (compact mode; slot 1 was already removed by another caller, so it's null):

[
  { "oid": "abc1Foo", "id": 42 },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 88 }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Moving a task under one of its own subtasks is such an error (400).

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. An item in another project is skipped too.

Order preservation (sliding chain): items are moved in submitted order. Items 1..N-1 are positioned after the previous successful move, regardless of the URL ?position= — without this, ?position=after R would reverse the batch.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

All items must belong to the project in the URL. Cross-project moves go through bulk-transfer.

projectOid: string
in path

Project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

Reference task OID (the destination anchor for the whole batch), or root to move items to the project root.

position: string parent, before, after
in query

(Optional) Placement of moved items relative to the reference: parent (default), before, or after. before / after require ?task= to refer to a task (not root).

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of moved tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error, ?task= missing, not found, or in another project, invalid ?position=, ?task=root&position=before|after, or an item moved under its own subtask. Whole batch rolled back.

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

404 Not Found

Not Found — project does not exist. (Item-level not-found is silent skip.)

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-transfer N tasks across projects by ID.

PUT /task/bulk-transfer/id/{sourceProjectId}

Example: PUT /task/bulk-transfer/id/my_project?project=archive_2026&task=root&return=compact

Transfers up to 300 tasks, with their subtasks, from the source project (URL path) to a different target project (?project=) in one transaction. Same query-param grammar as single-task PUT /task/transfer/...:

  • ?project={target} (required) — target project, or - for your personal tasks.
  • ?task={ref} (optional) — destination anchor in the target project. Omitted, empty, or root → items become root tasks of the target. A {ref} that isn't found there is rejected with 400.
  • ?position= — parent (default), before, or after.
  • ?invite, ?tag, ?status, ?custom-field — auto-remap flags, all on by default; any value but true, 1, or empty turns one off.

In the by-ID URL form, ?project= and ?task= are IDs; in the by-OID form, OIDs. Items in the body use the bulk mixed-form convention (OID / integer ID / #<id> string) — same as bulk-remove / bulk-move.

Request body (mixed-form refs):

[ 42, "#99", "iuRRiKoyrxdBFhFTTo" ]

Response (compact mode; OIDs are preserved across transfer, IDs are reassigned from the target's counter):

[
  { "oid": "abc1Foo",            "id": 7 },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 8 }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Both projects are rolled back.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. An item not in the source project (already in the target, or in another project) is skipped too.

Source == target: if ?project= resolves to the same project as the URL source, the whole batch is rejected with 400 (use bulk-move for within-project reorder).

Order preservation (sliding chain): items are transferred in submitted order — items 1..N-1 land after the previous successful transfer, regardless of ?position=.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write. Nothing is persisted in either project.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

sourceProjectId: string
in path

Source project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

project: string
in query

Target project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

(Optional) Reference task ID in the target project (destination anchor for the whole batch), or root to transfer items to the target project's root.

position: string parent, before, after
in query

(Optional) Placement of transferred items relative to the reference: parent (default), before, or after. before / after require ?task= to refer to a task (not root).

invite: string
in query

(Optional) Whether to invite assignees to the target project if they are not already members. It applies only if you are an admin of the target project (never when the target is -, your personal tasks); otherwise nobody is invited.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

tag: string
in query

(Optional) Whether to add tags to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

status: string
in query

(Optional) Whether to add statuses to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

custom-field: string
in query

(Optional) Whether to add non-empty custom fields to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of transferred tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error, missing ?project=, ?task= not found in the target, invalid ?position=, ?task=root&position=before|after, ?project= resolves to the URL source project, or any per-item validation failure. Whole batch rolled back.

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size); the target would go over its plan's task or storage quota; or a task (or a subtask) has reminders and the target's plan doesn't include reminders. Whole batch rolled back.

403 Forbidden

Forbidden — caller lacks permission on the source or target project, or on any individual task in the batch. Whole batch rolled back.

404 Not Found

Not Found — source or target project does not exist. (Item-level not-found is silent skip.)

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-transfer N tasks across projects by OID.

PUT /task/bulk-transfer/{sourceProjectOid}

Example: PUT /task/bulk-transfer/0Mg3VQ8kWeiVbLH1PrjzUc89?project=0Mg3VQ8kWeiVbLH1ArcvUc12&task=root&return=compact

Transfers up to 300 tasks, with their subtasks, from the source project (URL path) to a different target project (?project=) in one transaction. Same query-param grammar as single-task PUT /task/transfer/...:

  • ?project={target} (required) — target project, or - for your personal tasks.
  • ?task={ref} (optional) — destination anchor in the target project. Omitted, empty, or root → items become root tasks of the target. A {ref} that isn't found there is rejected with 400.
  • ?position= — parent (default), before, or after.
  • ?invite, ?tag, ?status, ?custom-field — auto-remap flags, all on by default; any value but true, 1, or empty turns one off.

In the by-ID URL form, ?project= and ?task= are IDs; in the by-OID form, OIDs. Items in the body use the bulk mixed-form convention (OID / integer ID / #<id> string) — same as bulk-remove / bulk-move.

Request body (mixed-form refs):

[ 42, "#99", "iuRRiKoyrxdBFhFTTo" ]

Response (compact mode; OIDs are preserved across transfer, IDs are reassigned from the target's counter):

[
  { "oid": "abc1Foo",            "id": 7 },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 8 }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Both projects are rolled back.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. An item not in the source project (already in the target, or in another project) is skipped too.

Source == target: if ?project= resolves to the same project as the URL source, the whole batch is rejected with 400 (use bulk-move for within-project reorder).

Order preservation (sliding chain): items are transferred in submitted order — items 1..N-1 land after the previous successful transfer, regardless of ?position=.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write. Nothing is persisted in either project.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

sourceProjectOid: string
in path

Source project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

project: string
in query

Target project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

(Optional) Reference task OID in the target project (destination anchor for the whole batch), or root to transfer items to the target project's root.

position: string parent, before, after
in query

(Optional) Placement of transferred items relative to the reference: parent (default), before, or after. before / after require ?task= to refer to a task (not root).

invite: string
in query

(Optional) Whether to invite assignees to the target project if they are not already members. It applies only if you are an admin of the target project (never when the target is -, your personal tasks); otherwise nobody is invited.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

tag: string
in query

(Optional) Whether to add tags to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

status: string
in query

(Optional) Whether to add statuses to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

custom-field: string
in query

(Optional) Whether to add non-empty custom fields to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]

OK — array of transferred tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error, missing ?project=, ?task= not found in the target, invalid ?position=, ?task=root&position=before|after, ?project= resolves to the URL source project, or any per-item validation failure. Whole batch rolled back.

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size); the target would go over its plan's task or storage quota; or a task (or a subtask) has reminders and the target's plan doesn't include reminders. Whole batch rolled back.

403 Forbidden

Forbidden — caller lacks permission on the source or target project, or on any individual task in the batch. Whole batch rolled back.

404 Not Found

Not Found — source or target project does not exist. (Item-level not-found is silent skip.)

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-update N tasks in a project by ID.

PUT /task/bulk-update/id/{projectId}

Example: PUT /task/bulk-update/id/my_project?return=compact

Updates up to 300 tasks in one transaction. Body is a top-level JSON array of BulkUpdateTaskItem — each item carries exactly one of oid / id — id may be an integer or a "#42" string — plus the UpdateTaskBody-shape fields to apply. Both or neither is rejected with 400.

Request body:

[
  { "id": 42, "status": 100, "addTags": ["done"] },
  { "id": 99, "addAssignees": ["alice@example.com"] },
  { "id": 17, "name": "Renamed" }
]

Tags must exist already in the project (or be global tags of its organization); an unknown tag is rejected with 400.

Response (compact mode; slot for a not-found item is null):

[
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 42 },
  null,
  { "oid": "defLmnQrSt", "id": 17 }
]

In full mode, each slot is the full updated task record, parent included.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Example error:

{ "code": 400, "message": "items[1]: Invalid value for `priority`: 99 (expected -1, 0, 1, or 2 (or one of Low/Medium/High/Urgent))" }

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  {
    "oid": "iuRRiKoyrxdBFhFTTo",
    "id": 42,
    "description": "This is a **cool** task.",
    "tags": "[\"urgent\", \"design\"]",
    "partner": "UI design team",
    "addTags": "[\"urgent\"]",
    "removeTags": "[\"draft\"]",
    "addAssignees": "[\"me\"]",
    "removeAssignees": "[\"alice@example.com\"]",
    "addFollowers": "[\"me\"]",
    "removeFollowers": "[\"bob@example.com\"]",
    "addSuccessors": "[\"#13\"]",
    "removeSuccessors": "[\"#13\"]",
    "assignees": "[\"me\", \"alice@example.com\"]",
    "start": "2026-05-01",
    "due": "2026-05-10T17:00Z",
    "recurrence": {
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "peekaboo": "true",
    "section": true,
    "milestone": true,
    "asUser": true,
    "followers": "[\"bob@example.com\"]",
    "successors": "[\"#13\"]",
    "yourField": "object",
    "name": "New idea",
    "status": 100,
    "etc": 0,
    "priority": 0,
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
  }
]

OK — array of updated tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error (both/neither oid and id, or a ref that is neither a string nor an integer), or any per-item validation failure (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

404 Not Found

Not Found — project does not exist. (Item-level not-found is silent skip.)

409 Conflict

Conflict — project settings block completing an item (an open predecessor, or a pending approval) (whole batch rolled back).

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (409 Conflict)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-update N tasks in a project by OID.

PUT /task/bulk-update/{projectOid}

Example: PUT /task/bulk-update/0Mg3VQ8kWeiVbLH1PrjzUc89?return=compact

Updates up to 300 tasks in one transaction. Body is a top-level JSON array of BulkUpdateTaskItem — each item carries exactly one of oid / id — id may be an integer or a "#42" string — plus the UpdateTaskBody-shape fields to apply. Both or neither is rejected with 400.

Request body:

[
  { "id": 42, "status": 100, "addTags": ["done"] },
  { "id": 99, "addAssignees": ["alice@example.com"] },
  { "id": 17, "name": "Renamed" }
]

Tags must exist already in the project (or be global tags of its organization); an unknown tag is rejected with 400.

Response (compact mode; slot for a not-found item is null):

[
  { "oid": "iuRRiKoyrxdBFhFTTo", "id": 42 },
  null,
  { "oid": "defLmnQrSt", "id": 17 }
]

In full mode, each slot is the full updated task record, parent included.

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry. Example error:

{ "code": 400, "message": "items[1]: Invalid value for `priority`: 99 (expected -1, 0, 1, or 2 (or one of Low/Medium/High/Urgent))" }

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

projectOid: string
in path

Project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

return: string full, compact
in query

(Optional) Response shape: full (default) gives each item's full task record; compact gives only {"oid": …, "id": …} per item. Recommended for large batches. Any other value returns 400 Bad Request.

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  {
    "oid": "iuRRiKoyrxdBFhFTTo",
    "id": 42,
    "description": "This is a **cool** task.",
    "tags": "[\"urgent\", \"design\"]",
    "partner": "UI design team",
    "addTags": "[\"urgent\"]",
    "removeTags": "[\"draft\"]",
    "addAssignees": "[\"me\"]",
    "removeAssignees": "[\"alice@example.com\"]",
    "addFollowers": "[\"me\"]",
    "removeFollowers": "[\"bob@example.com\"]",
    "addSuccessors": "[\"#13\"]",
    "removeSuccessors": "[\"#13\"]",
    "assignees": "[\"me\", \"alice@example.com\"]",
    "start": "2026-05-01",
    "due": "2026-05-10T17:00Z",
    "recurrence": {
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "peekaboo": "true",
    "section": true,
    "milestone": true,
    "asUser": true,
    "followers": "[\"bob@example.com\"]",
    "successors": "[\"#13\"]",
    "yourField": "object",
    "name": "New idea",
    "status": 100,
    "etc": 0,
    "priority": 0,
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
  }
]

OK — array of updated tasks (slots for not-found items are null).

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, item shape error (both/neither oid and id, or a ref that is neither a string nor an integer), or any per-item validation failure (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

404 Not Found

Not Found — project does not exist. (Item-level not-found is silent skip.)

409 Conflict

Conflict — project settings block completing an item (an open predecessor, or a pending approval) (whole batch rolled back).

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "tags": [
      {
        "color": "35",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "successors": "[\"#135\", \"#26\"]",
    "predecessors": "[\"#17\", \"#66\", \"#91\"]",
    "successorRefs": [
      {
        "id": 12,
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "predecessorRefs": [
      "#/definitions/TaskRef"
    ],
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "id": 12,
    "nameText": "Design new logo",
    "nameHtml": "Design new <b>logo</b>",
    "name": "Design new **logo**",
    "description": "This is a *cool* task.",
    "descriptionText": "This is a cool task.",
    "descriptionHtml": "This is a <i>cool</i> task.",
    "timelogs": [
      {
        "start": "2023-02-20T00:00:00.000Z",
        "end": "2023-02-20T00:05:35.000Z",
        "user": {
          "url": "https://quire.io/u/my_id",
          "id": "my_id",
          "iconColor": "37",
          "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
          "name": "Foo",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        },
        "billable": true,
        "note": "A piece of cake"
      }
    ],
    "etc": 500,
    "recurrence": {
      "seriesId": "j47xvxul26",
      "byweekday": "[1,3]",
      "byweekno": 2,
      "bydayno": 25,
      "bymonth": 10,
      "dupsubtasks": false,
      "sincelatest": true,
      "freq": "weekly",
      "interval": 1,
      "until": "2020-12-22"
    },
    "status": {
      "value": 0,
      "name": "To-do",
      "color": "50"
    },
    "start": "2026-05-01",
    "due": "2026-05-10",
    "priority": {
      "value": 0,
      "name": "Medium"
    },
    "partner": "#/definitions/SimpleTaggingEntity",
    "assignors": [
      {
        "name": "John Doe",
        "id": "john_doe",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      }
    ],
    "partnerBy": "#/definitions/TaskUser",
    "assignees": [
      "#/definitions/TaskUser"
    ],
    "order": 99,
    "attachments": [
      {
        "type": 2,
        "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
        "length": 20000,
        "name": "file.txt",
        "createdBy": "#/definitions/SimpleIdentity",
        "createdAt": "2018-12-22T02:06:58.158Z"
      }
    ],
    "cover": "qfqVmUtC",
    "childCount": 5,
    "peekaboo": true,
    "section": true,
    "milestone": true,
    "url": "https://quire.io/w/my_project/123",
    "mutes": [
      "#/definitions/TaskUser"
    ],
    "followers": [
      "#/definitions/TaskUser"
    ],
    "favorites": [
      "#/definitions/TaskUser"
    ],
    "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
    "toggledAt": "2018-12-22T02:06:58.158Z",
    "toggledBy": "#/definitions/TaskUser"
  }
]
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (404 Not Found)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (409 Conflict)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Move an existing task by its ID.

PUT /task/move/id/{projectId}/{taskId}

Moves an existing task, with its subtasks, under another task as a subtask, reorders it among siblings, or sends it to the root level, within its project. To move it to another project, use the transfer endpoints.

Use ?task= to name the reference task and ?position= to choose placement (parent / before / after); ?task=root moves it to the root level.

Returns the updated task record. A ?task= that isn't found, or is in another project, is rejected with 400, as is moving a task under one of its own subtasks.

Examples:

  • PUT /task/move/id/my_project/42?task=99 — reparent (default: child of task 99).
  • PUT /task/move/id/my_project/42?task=99&position=before — place task 42 before task 99.
  • PUT /task/move/id/my_project/42?task=99&position=after — place task 42 after task 99.
  • PUT /task/move/id/my_project/42?task=root — move to root level.
  • PUT /task/move/iuRRiKoyrxdBFhFTTo?task=0Mg3VQ8kWeiVbLH1JjvzUcP7&position=after — the same by OID: in this form, ?task= is a task OID.
projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Task ID to be moved.

task: string
in query

Reference task ID. How it's used depends on position:

  • parent (default): the moved task becomes a child of task.
  • before / after: the moved task is placed as a sibling, under task's parent.

Specify root to move to the root level (only valid with the default parent position).

position: string parent, before, after
in query

(Optional) Placement relative to task:

  • parent (default): child of task.
  • before: sibling immediately before task.
  • after: sibling immediately after task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request. before / after require task to refer to a task (not root).

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — updated task record.

400 Bad Request

Bad Request — task missing, not found, or in another project; invalid position; or the new parent is one of the task's subtasks.

403 Forbidden

Forbidden — caller lacks permission to move this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Move an existing task by its OID.

PUT /task/move/{oid}

Moves an existing task, with its subtasks, under another task as a subtask, reorders it among siblings, or sends it to the root level, within its project. To move it to another project, use the transfer endpoints.

Use ?task= to name the reference task and ?position= to choose placement (parent / before / after); ?task=root moves it to the root level.

Returns the updated task record. A ?task= that isn't found, or is in another project, is rejected with 400, as is moving a task under one of its own subtasks.

Examples:

  • PUT /task/move/id/my_project/42?task=99 — reparent (default: child of task 99).
  • PUT /task/move/id/my_project/42?task=99&position=before — place task 42 before task 99.
  • PUT /task/move/id/my_project/42?task=99&position=after — place task 42 after task 99.
  • PUT /task/move/id/my_project/42?task=root — move to root level.
  • PUT /task/move/iuRRiKoyrxdBFhFTTo?task=0Mg3VQ8kWeiVbLH1JjvzUcP7&position=after — the same by OID: in this form, ?task= is a task OID.
oid: string
in path

Task OID to be moved.

task: string
in query

Reference task OID. How it's used depends on position:

  • parent (default): the moved task becomes a child of task.
  • before / after: the moved task is placed as a sibling, under task's parent.

Specify root to move to the root level (only valid with the default parent position).

position: string parent, before, after
in query

(Optional) Placement relative to task:

  • parent (default): child of task.
  • before: sibling immediately before task.
  • after: sibling immediately after task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request. before / after require task to refer to a task (not root).

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — updated task record.

400 Bad Request

Bad Request — task missing, not found, or in another project; invalid position; or the new parent is one of the task's subtasks.

403 Forbidden

Forbidden — caller lacks permission to move this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Transfer an existing task by its ID to another project.

PUT /task/transfer/id/{projectId}/{taskId}

Transfers an existing task, with its subtasks, to another project, optionally positioning it relative to an existing task in the target (?task= + ?position=). The task keeps its OID but gets an ID in the target project, usually a new one — read it from the response. The target can't be the task's own project (400; use move instead).

?invite, ?tag, ?status, and ?custom-field (all on by default) bring the assignees, tags, statuses, and custom fields the task uses into the target project.

Reminders on the task and its subtasks move with it. If the target's plan doesn't include reminders, or the transfer would take the target past its plan's task or storage quota, the call is rejected with 402 (code 469) and nothing changes.

Returns the updated task record.

Examples:

  • PUT /task/transfer/id/my_project/42?project=archive — transfer to root of target project.
  • PUT /task/transfer/id/my_project/42?project=archive&task=99 — transfer as a child of task 99 in target.
  • PUT /task/transfer/id/my_project/42?project=archive&task=99&position=before — transfer and place before task 99.
  • PUT /task/transfer/id/my_project/42?project=- — transfer to your personal tasks.
  • PUT /task/transfer/iuRRiKoyrxdBFhFTTo?project=0Mg3VQ8kWeiVbLH1PrjzUc89 — the same by OID: in this form, ?project= and ?task= are OIDs.
projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Task ID to be transferred.

project: string
in query

ID of the target project to which the task will be transferred. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

(Optional) ID of a reference task in the target project. How it's used depends on position:

  • parent (default): the transferred task becomes a child of task.
  • before / after: the transferred task is placed as a sibling, under task's parent.

If omitted (or root), the transferred task becomes a root task in the target project.

position: string parent, before, after
in query

(Optional) Placement relative to task in the target project:

  • parent (default): child of task.
  • before: sibling immediately before task.
  • after: sibling immediately after task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request. before / after require task to refer to a task (not omitted, not root).

invite: string
in query

(Optional) Whether to invite assignees to the target project if they are not already members. It applies only if you are an admin of the target project (never when the target is -, your personal tasks); otherwise nobody is invited.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

tag: string
in query

(Optional) Whether to add tags to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

status: string
in query

(Optional) Whether to add statuses to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

custom-field: string
in query

(Optional) Whether to add non-empty custom fields to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — updated task record.

400 Bad Request

Bad Request — project missing or the task's own project; task not found in the target project; or invalid position.

402 Payment Required

Payment Required (code 469) — the target would go over its plan's task or storage quota, or the task (or a subtask) has reminders and the target's plan doesn't include reminders.

403 Forbidden

Forbidden — caller lacks permission to transfer this task.

404 Not Found

Not Found — task or target project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Transfer an existing task by its OID to another project.

PUT /task/transfer/{oid}

Transfers an existing task, with its subtasks, to another project, optionally positioning it relative to an existing task in the target (?task= + ?position=). The task keeps its OID but gets an ID in the target project, usually a new one — read it from the response. The target can't be the task's own project (400; use move instead).

?invite, ?tag, ?status, and ?custom-field (all on by default) bring the assignees, tags, statuses, and custom fields the task uses into the target project.

Reminders on the task and its subtasks move with it. If the target's plan doesn't include reminders, or the transfer would take the target past its plan's task or storage quota, the call is rejected with 402 (code 469) and nothing changes.

Returns the updated task record.

Examples:

  • PUT /task/transfer/id/my_project/42?project=archive — transfer to root of target project.
  • PUT /task/transfer/id/my_project/42?project=archive&task=99 — transfer as a child of task 99 in target.
  • PUT /task/transfer/id/my_project/42?project=archive&task=99&position=before — transfer and place before task 99.
  • PUT /task/transfer/id/my_project/42?project=- — transfer to your personal tasks.
  • PUT /task/transfer/iuRRiKoyrxdBFhFTTo?project=0Mg3VQ8kWeiVbLH1PrjzUc89 — the same by OID: in this form, ?project= and ?task= are OIDs.
oid: string
in path

Task OID to be transferred.

project: string
in query

OID of the target project to which the task will be transferred. Specify - for your personal tasks (those in My Tasks that belong to no project).

task: string
in query

(Optional) OID of a reference task in the target project. How it's used depends on position:

  • parent (default): the transferred task becomes a child of task.
  • before / after: the transferred task is placed as a sibling, under task's parent.

If omitted (or root), the transferred task becomes a root task in the target project.

position: string parent, before, after
in query

(Optional) Placement relative to task in the target project:

  • parent (default): child of task.
  • before: sibling immediately before task.
  • after: sibling immediately after task.

Omitted or empty → same as parent. Any other value returns 400 Bad Request. before / after require task to refer to a task (not omitted, not root).

invite: string
in query

(Optional) Whether to invite assignees to the target project if they are not already members. It applies only if you are an admin of the target project (never when the target is -, your personal tasks); otherwise nobody is invited.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

tag: string
in query

(Optional) Whether to add tags to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

status: string
in query

(Optional) Whether to add statuses to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

custom-field: string
in query

(Optional) Whether to add non-empty custom fields to the target project if they are not already present.

On by default: omitted, true, 1, or an empty value keeps it on; any other value, e.g. false, turns it off.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — updated task record.

400 Bad Request

Bad Request — project missing or the task's own project; task not found in the target project; or invalid position.

402 Payment Required

Payment Required (code 469) — the target would go over its plan's task or storage quota, or the task (or a subtask) has reminders and the target's plan doesn't include reminders.

403 Forbidden

Forbidden — caller lacks permission to transfer this task.

404 Not Found

Not Found — task or target project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of a task by its ID.

PUT /task/undo-remove/id/{projectId}/{taskId}

Restores a previously-removed task, with the subtasks removed along with it, and its removed ancestors. Idempotent: if the task is not currently removed, this is a no-op and returns the current task record.

Restored tasks count toward the plan's task limit, as created ones do: if restoring them (subtasks and ancestors included) would go past it, nothing is restored and the call returns 402 (code 469).

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

taskId: integer
in path

Task ID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — restored task record.

402 Payment Required

Payment Required (code 469) — restoring would go past the plan's task limit; nothing is restored.

403 Forbidden

Forbidden — caller lacks permission to restore this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Undo the removal of a task by its OID.

PUT /task/undo-remove/{oid}

Restores a previously-removed task, with the subtasks removed along with it, and its removed ancestors. Idempotent: if the task is not currently removed, this is a no-op and returns the current task record.

Restored tasks count toward the plan's task limit, as created ones do: if restoring them (subtasks and ancestors included) would go past it, nothing is restored and the call returns 402 (code 469).

oid: string
in path

Task OID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

OK — restored task record.

402 Payment Required

Payment Required (code 469) — restoring would go past the plan's task limit; nothing is restored.

403 Forbidden

Forbidden — caller lacks permission to restore this task.

404 Not Found

Not Found — task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Update an existing time log on a task by ID.

PUT /task/update-timelog/id/{projectId}/{taskId}

Updates an existing time log on the task. The log to update is located by the start, end, and (optional) user query parameters — that triple is the log's identity. The body carries new values; any field omitted or set to null preserves the existing value (so an agent that always includes every field with null for unchanged ones is safe). To clear note, send an empty string.

Sub-second precision in time values is truncated to whole seconds (in both query params and body).

On success returns the task's full timelogs array. If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example:

[
  {
    "start": "2026-04-26T09:15:00.000Z",
    "end": "2026-04-26T10:45:00.000Z",
    "billable": true,
    "note": "Updated note",
    "user": { "oid": "u-123", "name": "John Doe" }
  }
]
projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

start: string
in query

Start timestamp of the existing log (identifies the log together with end and user). ISO 8601, UTC.

end: string
in query

End timestamp of the existing log. ISO 8601, UTC.

user: string
in query

(Optional) User the existing log is credited to (OID, ID, or email). Omitted defaults to the authenticated caller.

end: string

(Optional) New end timestamp (ISO 8601, UTC). Must be on or after the (new or existing) start. Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

user: string

(Optional) New user the log is credited to (OID, ID, or email). Omit or set null to preserve. Send empty string to reset to the authenticated caller.

billable: boolean

(Optional) New billable flag. Omit or set null to preserve.

note: string

(Optional) New note. Omit or set null to preserve. Send empty string to clear.

start: string

(Optional) New start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

Request Example
{
  "end": "2026-04-26T10:45:00Z",
  "user": "john.doe@example.com",
  "billable": false,
  "note": "Updated note",
  "start": "2026-04-26T09:15:00Z"
}
200 OK

OK — task's full timelogs array.

400 Bad Request

Bad Request — start / end query params missing or malformed, end precedes start (in the query or the new values), a user (in the query or the body) is unknown, or a body field has the wrong type.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — no log matches the identifying triple, or the task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]

Update an existing time log on a task by OID.

PUT /task/update-timelog/{oid}

Updates an existing time log on the task. The log to update is located by the start, end, and (optional) user query parameters — that triple is the log's identity. The body carries new values; any field omitted or set to null preserves the existing value (so an agent that always includes every field with null for unchanged ones is safe). To clear note, send an empty string.

Sub-second precision in time values is truncated to whole seconds (in both query params and body).

On success returns the task's full timelogs array. If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example:

[
  {
    "start": "2026-04-26T09:15:00.000Z",
    "end": "2026-04-26T10:45:00.000Z",
    "billable": true,
    "note": "Updated note",
    "user": { "oid": "u-123", "name": "John Doe" }
  }
]

See also the by-ID form PUT /task/update-timelog/id/{projectId}/{taskId}.

oid: string
in path

Task OID.

start: string
in query

Start timestamp of the existing log (identifies the log together with end and user). ISO 8601, UTC.

end: string
in query

End timestamp of the existing log. ISO 8601, UTC.

user: string
in query

(Optional) User the existing log is credited to (OID, ID, or email). Omitted defaults to the authenticated caller.

end: string

(Optional) New end timestamp (ISO 8601, UTC). Must be on or after the (new or existing) start. Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

user: string

(Optional) New user the log is credited to (OID, ID, or email). Omit or set null to preserve. Send empty string to reset to the authenticated caller.

billable: boolean

(Optional) New billable flag. Omit or set null to preserve.

note: string

(Optional) New note. Omit or set null to preserve. Send empty string to clear.

start: string

(Optional) New start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

Request Example
{
  "end": "2026-04-26T10:45:00Z",
  "user": "john.doe@example.com",
  "billable": false,
  "note": "Updated note",
  "start": "2026-04-26T09:15:00Z"
}
200 OK

OK — task's full timelogs array.

400 Bad Request

Bad Request — start / end query params missing or malformed, end precedes start (in the query or the new values), a user (in the query or the body) is unknown, or a body field has the wrong type.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — no log matches the identifying triple, or the task does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]

Update an existing task by its ID.

PUT /task/id/{projectId}/{taskId}

Updates an existing task and returns the updated record.

Only the fields you include are updated; omitted fields are left unchanged. Example — complete the task, add a tag, and remove an assignee:

{
  "status": 100,
  "addTags": ["done"],
  "removeAssignees": ["alice@example.com"]
}

Tags must exist already, as tags of the project or global tags of its organization: an unknown tag, like done here if the project has none, is rejected with 400, not created.

Note the replace-vs-incremental pattern: tags replaces the entire tag set; addTags / removeTags modify the set in place. Same for assignees / addAssignees / removeAssignees, and followers / successors / etc. Mix whichever suits the intent.

To archive (hide indefinitely) or snooze a task, set the peekaboo field: true hides it indefinitely, a positive integer hides it for that many days (above 10000: until that time, in milliseconds since the epoch), a date/time string such as 2026-11-04T09:30Z hides it until then (date only: 6 AM that day in the user's time zone), false unhides. A time must be in the future, otherwise 400, and the task shows again within the hour after it.

projectId: string
in path

ID of the task's project. Specify "-" for personal tasks in My Tasks.

taskId: integer
in path

Task ID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) New task description. An embedded data: image is rejected — upload the image as an attachment instead.

tags: string[]

(Optional) Tags to replace the current tags on this task (OID or name). This replaces all existing tags. To modify incrementally, use addTags or removeTags. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, is rejected with 400. The API can't remove it: null is rejected too.

addTags: string[]

(Optional) Tags to add to this task (OID or name). Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

removeTags: string[]

(Optional) Tags to remove from this task (OID or name). Tag names are case-insensitive. An unknown tag is rejected with 400.

addAssignees: string[]

(Optional) Assignees to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include all assignees of the parent task

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

removeAssignees: string[]

(Optional) Assignees to remove (OID, ID, or email).

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

addFollowers: string[]

(Optional) Followers to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers to remove (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": remove followers that were inherited from the parent task
  • "app": the application

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

addSuccessors: string[]

(Optional) Successors to add (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

removeSuccessors: string[]

(Optional) Successors to remove (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

assignees: string[]

(Optional) Assignees to replace the current assignees (OID, ID, or email). This replaces all existing assignees. To modify incrementally, use addAssignees or removeAssignees.

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
  • null clears it. It is rejected if the task is recurring, since a recurring task always has a due; pass recurrence: null in the same request to stop repeating and clear the due together.
recurrence: Recurrence

(Optional) Makes the task repeat, replacing its current recurrence, if any. null stops it repeating.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If the task has none and due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely (task and subtasks).
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Undo previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

section: boolean

(Optional) true makes this task a section; false makes it a normal task. If both section and milestone are sent, only section is applied.

milestone: boolean

(Optional) true makes this task a milestone; false makes it a normal task. Ignored if section is sent too.

asUser: boolean

(Optional) If true, marks this update as performed by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (updated by the authorizing user). In bulk-update, each item has its own.

followers: string[]

(Optional) Followers to replace the current followers (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

successors: string[]

(Optional) Successors to replace the current successors (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted); send an entry back unchanged to keep that file.
  • Multi-value (fields configured with multiple: true): provide a list. Pass null to clear the field.

A field you can't view or edit (the definition's viewMembers and editMembers) is rejected with 400; locked stops editing in Quire only, not through the API.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

(Optional) New task name.

status: integer

(Optional) New status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Specify 100 to complete the task. Completion may be rejected (409 Conflict) when project settings require all predecessors to be completed first, or require an approval to be granted.

etc: integer

(Optional) Estimated time to complete, in seconds. Must be 0 to 864,000,000 (10,000 days) or null. Specify null to clear the value.

priority: integer -1, 0, 1, 2

(Optional) New priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.)

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
  • It replaces the stored object as a whole: keys you leave out are removed, and null removes sourceRef. Another app may have stored its own key on the task; to keep it, read the task first and send that key back.
Request Example
{
  "description": "This is a **cool** task.",
  "tags": [
    "ITaVbkhh3iVcEcV3vuSLeE2k"
  ],
  "partner": "UI design team",
  "addTags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "removeTags": [
    "mPAQrYU1qt8wAYAInKRlTnvl"
  ],
  "addAssignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "removeAssignees": [
    "Job4NSW9xK6Owcke8iKj7zyH"
  ],
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "addSuccessors": "[\"#13\"]",
  "removeSuccessors": "[\"#13\"]",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "New idea",
  "status": 100,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}

OK — updated task record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to update this task.

404 Not Found

Not Found — task does not exist.

409 Conflict

Conflict — project settings block completing the task (an open predecessor, or a pending approval). Resolve it, then retry.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Update an existing task by its OID.

PUT /task/{oid}

Updates an existing task and returns the updated record.

Only the fields you include are updated; omitted fields are left unchanged. Example — complete the task, add a tag, and remove an assignee:

{
  "status": 100,
  "addTags": ["done"],
  "removeAssignees": ["alice@example.com"]
}

Tags must exist already, as tags of the project or global tags of its organization: an unknown tag, like done here if the project has none, is rejected with 400, not created.

Note the replace-vs-incremental pattern: tags replaces the entire tag set; addTags / removeTags modify the set in place. Same for assignees / addAssignees / removeAssignees, and followers / successors / etc. Mix whichever suits the intent.

To archive (hide indefinitely) or snooze a task, set the peekaboo field: true hides it indefinitely, a positive integer hides it for that many days (above 10000: until that time, in milliseconds since the epoch), a date/time string such as 2026-11-04T09:30Z hides it until then (date only: 6 AM that day in the user's time zone), false unhides. A time must be in the future, otherwise 400, and the task shows again within the hour after it.

oid: string
in path

Task OID.

return: string full, compact
in query

(Optional) Response shape:

  • full (default): the full task record.
  • compact: only {"oid": …, "id": …} — the task's OID and ID. Saves payload, tokens, and a server-side reload; enough to chain follow-up calls.

Any other value returns 400 Bad Request.

description: string

(Optional) New task description. An embedded data: image is rejected — upload the image as an attachment instead.

tags: string[]

(Optional) Tags to replace the current tags on this task (OID or name). This replaces all existing tags. To modify incrementally, use addTags or removeTags. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, is rejected with 400. The API can't remove it: null is rejected too.

addTags: string[]

(Optional) Tags to add to this task (OID or name). Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

removeTags: string[]

(Optional) Tags to remove from this task (OID or name). Tag names are case-insensitive. An unknown tag is rejected with 400.

addAssignees: string[]

(Optional) Assignees to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include all assignees of the parent task

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

removeAssignees: string[]

(Optional) Assignees to remove (OID, ID, or email).

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

addFollowers: string[]

(Optional) Followers to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

removeFollowers: string[]

(Optional) Followers to remove (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": remove followers that were inherited from the parent task
  • "app": the application

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

addSuccessors: string[]

(Optional) Successors to add (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

removeSuccessors: string[]

(Optional) Successors to remove (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

assignees: string[]

(Optional) Assignees to replace the current assignees (OID, ID, or email). This replaces all existing assignees. To modify incrementally, use addAssignees or removeAssignees.

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
  • null clears it. It is rejected if the task is recurring, since a recurring task always has a due; pass recurrence: null in the same request to stop repeating and clear the due together.
recurrence: Recurrence

(Optional) Makes the task repeat, replacing its current recurrence, if any. null stops it repeating.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If the task has none and due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely (task and subtasks).
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Undo previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

section: boolean

(Optional) true makes this task a section; false makes it a normal task. If both section and milestone are sent, only section is applied.

milestone: boolean

(Optional) true makes this task a milestone; false makes it a normal task. Ignored if section is sent too.

asUser: boolean

(Optional) If true, marks this update as performed by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (updated by the authorizing user). In bulk-update, each item has its own.

followers: string[]

(Optional) Followers to replace the current followers (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

successors: string[]

(Optional) Successors to replace the current successors (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted); send an entry back unchanged to keep that file.
  • Multi-value (fields configured with multiple: true): provide a list. Pass null to clear the field.

A field you can't view or edit (the definition's viewMembers and editMembers) is rejected with 400; locked stops editing in Quire only, not through the API.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

(Optional) New task name.

status: integer

(Optional) New status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Specify 100 to complete the task. Completion may be rejected (409 Conflict) when project settings require all predecessors to be completed first, or require an approval to be granted.

etc: integer

(Optional) Estimated time to complete, in seconds. Must be 0 to 864,000,000 (10,000 days) or null. Specify null to clear the value.

priority: integer -1, 0, 1, 2

(Optional) New priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.)

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
  • It replaces the stored object as a whole: keys you leave out are removed, and null removes sourceRef. Another app may have stored its own key on the task; to keep it, read the task first and send that key back.
Request Example
{
  "description": "This is a **cool** task.",
  "tags": [
    "ITaVbkhh3iVcEcV3vuSLeE2k"
  ],
  "partner": "UI design team",
  "addTags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "removeTags": [
    "mPAQrYU1qt8wAYAInKRlTnvl"
  ],
  "addAssignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "removeAssignees": [
    "Job4NSW9xK6Owcke8iKj7zyH"
  ],
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "addSuccessors": "[\"#13\"]",
  "removeSuccessors": "[\"#13\"]",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "New idea",
  "status": 100,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}

OK — updated task record.

400 Bad Request

Bad Request — body validation failed.

403 Forbidden

Forbidden — caller lacks permission to update this task.

404 Not Found

Not Found — task does not exist.

409 Conflict

Conflict — project settings block completing the task (an open predecessor, or a pending approval). Resolve it, then retry.

Response Content-Types: application/json
Response Example (200 OK)
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z"
}

Bulk-remove N tasks from a project by ID.

DELETE /task/bulk-remove/id/{projectId}

Example: DELETE /task/bulk-remove/id/my_project

Removes up to 300 tasks, with their subtasks, in one transaction. Restore any of them with PUT /task/undo-remove/.... Body is a top-level JSON array of task references — each element is one of:

  • a task OID (string),
  • an integer task ID, or
  • a "#<id>" string (the ID-with-hash form).

Mixed forms in the same batch are allowed.

Request body (mixed forms — all three reference shapes in one batch):

[ 42, "#99", "iuRRiKoyrxdBFhFTTo" ]

Response — always {oid} per item, whatever ?return= (slot 1 didn't resolve — already removed — so it's null):

[
  { "oid": "abc1Foo" },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo" }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. If the project itself doesn't exist, it returns 204 No Content with no body, like deleting a task.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

projectId: string
in path

Project ID. Specify - for your personal tasks (those in My Tasks that belong to no project).

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]
200 OK

OK — array of {oid} elements (slots for not-found items are null).

204 No Content

No Content — the project does not exist; nothing is removed. (Item-level not-found is silent skip.)

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, or any item is neither a string nor an integer (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
"object"
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Bulk-remove N tasks from a project by OID.

DELETE /task/bulk-remove/{projectOid}

Example: DELETE /task/bulk-remove/0Mg3VQ8kWeiVbLH1PrjzUc89

Removes up to 300 tasks, with their subtasks, in one transaction. Restore any of them with PUT /task/undo-remove/.... Body is a top-level JSON array of task references — each element is one of:

  • a task OID (string),
  • an integer task ID, or
  • a "#<id>" string (the ID-with-hash form).

Mixed forms in the same batch are allowed.

Request body (mixed forms — all three reference shapes in one batch):

[ 42, "#99", "iuRRiKoyrxdBFhFTTo" ]

Response — always {oid} per item, whatever ?return= (slot 1 didn't resolve — already removed — so it's null):

[
  { "oid": "abc1Foo" },
  null,
  { "oid": "iuRRiKoyrxdBFhFTTo" }
]

Atomic: a per-item validation, permission, or DB error rolls back the whole batch and returns {code, message} with an items[i]: prefix naming the offending item. Fix the value and retry.

Skip-not-found: a ref that doesn't resolve to a live task in the project (already removed, never existed, a mistyped OID, cascade-removed by an earlier item, etc.) is skipped — its response slot is null and the rest of the batch proceeds. This makes the endpoint idempotent for agents — safe to re-submit after a partial network failure without diffing state first. Only a ref that is neither a string nor an integer is rejected with 400. If the project itself doesn't exist, it returns 204 No Content with no body, like deleting a task.

Dry-run: pass ?dry-run=true to preview the call without persisting any changes. Same per-item validation and permission checks as a real call; same response body shape on success and same {code, message} (with items[i]: prefix) on failure. A 200 from a dry-run is a strong signal that re-issuing the identical body without ?dry-run will succeed (subject to concurrent edits between the two calls). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Rate-limit cost: 1 unit per item, charged upfront — for bulk-add, per task created, nested tasks included. ?dry-run=true costs ceil(N / 2) units (minimum 1). Skipped items are charged too. See Rate Limits.

Batch size: at most 300 items per call, and no more than the plan's per-minute rate limit — e.g. 50 on the Free plan, or 25 in a personal project on the Free plan (see Rate Limits). A batch over the plan's cap is rejected with 402 (code 469), one over 300 with 400; split it.

projectOid: string
in path

Project OID. Specify - for your personal tasks (those in My Tasks that belong to no project).

dry-run: string true, false
in query

(Optional) Set to true to preview the call without persisting any changes. Same validation, permissions, and response shape as a real call, at half the rate-limit cost (ceil(N / 2) units). Only true, 1, or an empty value turns it on; any other value, even yes, makes a real write.

Request Example
[
  "object"
]
200 OK

OK — array of {oid} elements (slots for not-found items are null).

204 No Content

No Content — the project does not exist; nothing is removed. (Item-level not-found is silent skip.)

400 Bad Request

Bad Request — body not a JSON array, empty, over the 300-item cap, or any item is neither a string nor an integer (whole batch rolled back).

402 Payment Required

Payment Required (code 469) — the batch holds more items than the plan allows per call (see Batch size).

403 Forbidden

Forbidden — caller lacks permission on the project or any task in the batch (whole batch rolled back).

413 Request Entity Too Large

Payload Too Large — body exceeds the API packet size limit.

429 Too Many Requests

Too Many Requests — the caller's per-minute / per-hour API quota is already used up (see Rate Limits).

Response Content-Types: application/json
Response Example (200 OK)
"object"
Response Example (400 Bad Request)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (402 Payment Required)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (403 Forbidden)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (413 Request Entity Too Large)
{
  "code": 429,
  "message": "Something went wrong."
}
Response Example (429 Too Many Requests)
{
  "code": 429,
  "message": "Something went wrong."
}

Remove a time log from a task by ID.

DELETE /task/remove-timelog/id/{projectId}/{taskId}

Removes the time log identified by the (user, start, end) triple from the task. Sub-second precision in the query params is truncated to whole seconds before matching.

On success returns the task's remaining timelogs array (empty when no logs remain). If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example after removing the only log:

[]

Note: Like deleting a task, returns 204 No Content if the task or the project doesn't exist, or the task has been deleted. Nothing is changed. Unlike deleting a task, it returns 404 if the task exists but no log matches the triple.

projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

start: string
in query

Start timestamp of the log to remove. ISO 8601, UTC.

end: string
in query

End timestamp of the log to remove. ISO 8601, UTC.

user: string
in query

(Optional) User the existing log is credited to (OID, ID, or email). Omitted defaults to the authenticated caller.

200 OK

OK — task's remaining timelogs array (empty when none remain).

204 No Content

No Content — the task doesn't exist, or has been deleted; nothing is changed.

400 Bad Request

Bad Request — start / end query params missing or malformed, end precedes start, or user is unknown.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — no log matches the triple.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]

Remove a time log from a task by OID.

DELETE /task/remove-timelog/{oid}

Removes the time log identified by the (user, start, end) triple from the task. Sub-second precision in the query params is truncated to whole seconds before matching.

On success returns the task's remaining timelogs array (empty when no logs remain). If the project hides time logs from guests (its default), a guest member or a non-member gets an empty array, as timelogs is omitted from the task records they get. Example after removing the only log:

[]

Note: Like deleting a task, returns 204 No Content if the task or the project doesn't exist, or the task has been deleted. Nothing is changed. Unlike deleting a task, it returns 404 if the task exists but no log matches the triple.

See also the by-ID form DELETE /task/remove-timelog/id/{projectId}/{taskId}.

oid: string
in path

Task OID.

start: string
in query

Start timestamp of the log to remove. ISO 8601, UTC.

end: string
in query

End timestamp of the log to remove. ISO 8601, UTC.

user: string
in query

(Optional) User the existing log is credited to (OID, ID, or email). Omitted defaults to the authenticated caller.

200 OK

OK — task's remaining timelogs array (empty when none remain).

204 No Content

No Content — the task doesn't exist, or has been deleted; nothing is changed.

400 Bad Request

Bad Request — start / end query params missing or malformed, end precedes start, or user is unknown.

403 Forbidden

Forbidden — the caller can't change this task's time logs (checked before the log is looked up).

404 Not Found

Not Found — no log matches the triple.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "start": "2023-02-20T00:00:00.000Z",
    "end": "2023-02-20T00:05:35.000Z",
    "user": {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    },
    "billable": true,
    "note": "A piece of cake"
  }
]

Cancel a task's approval.

DELETE /task/revoke-approval/id/{projectId}/{taskId}

Revokes the task's current approval. The effect depends on the current state:

  • approved / rejected → rolls the decision back to awaiting. Only an approver of the category can do it; the caller becomes the approval's approver, and the original requester is preserved. The approval can then be decided again via POST /task/approve/....
  • awaiting / changes → clears the approval entirely. Only the requester can do it, and only while a claimer of the category; once the requester has left the project, any claimer can.

A category's approvers and claimers are its approvers / claimers: anyone in the project if unset, admins only if [], or the listed users. Anyone else gets 403.

Idempotent: returns 204 No Content even when no approval is set, or the task doesn't exist.

projectId: string
in path

Project ID.

taskId: integer
in path

Task ID.

204 No Content

No Content — approval revoked (or already absent).

403 Forbidden

Forbidden — the caller can't revoke this approval (see the rules above).

Response Content-Types: application/json

Cancel a task's approval by OID.

DELETE /task/revoke-approval/{oid}

Revokes the task's current approval. The effect depends on the current state:

  • approved / rejected → rolls the decision back to awaiting. Only an approver of the category can do it; the caller becomes the approval's approver, and the original requester is preserved. The approval can then be decided again via POST /task/approve/....
  • awaiting / changes → clears the approval entirely. Only the requester can do it, and only while a claimer of the category; once the requester has left the project, any claimer can.

A category's approvers and claimers are its approvers / claimers: anyone in the project if unset, admins only if [], or the listed users. Anyone else gets 403.

Idempotent: returns 204 No Content even when no approval is set, or the task doesn't exist.

See also the by-ID form DELETE /task/revoke-approval/id/{projectId}/{taskId}.

oid: string
in path

Task OID.

204 No Content

No Content — approval revoked (or already absent).

403 Forbidden

Forbidden — the caller can't revoke this approval (see the rules above).

Response Content-Types: application/json

Delete a task and all of its subtasks by its ID.

DELETE /task/id/{projectId}/{taskId}

Deletes an existing task and all of its subtasks. Restore them with PUT /task/undo-remove/id/{projectId}/{taskId} (or PUT /task/undo-remove/{oid}).

Note: Returns 204 No Content regardless of whether the task exists.

projectId: string
in path

Project ID. Specify "-" to remove from personal tasks in My Tasks.

taskId: integer
in path

Task ID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to delete this task.

Response Content-Types: application/json

Delete a task and all of its subtasks by its OID.

DELETE /task/{oid}

Deletes an existing task and all of its subtasks. Restore them with PUT /task/undo-remove/id/{projectId}/{taskId} (or PUT /task/undo-remove/{oid}).

Note: Returns 204 No Content regardless of whether the task exists.

oid: string
in path

Task OID.

204 No Content

No Content

403 Forbidden

Forbidden — caller lacks permission to delete this task.

Response Content-Types: application/json

user

Represents a Quire account that can access organizations, projects, and tasks.

Get a user by ID or email address.

GET /user/id/{id}

Returns the full user record for the given user ID, email address, or "me" (the current user). A colleague (someone sharing an organization, project or external team with the user) who hasn't authorized this app is returned with only oid, id and the name fields, unless the user granted the app access to contacts. Anyone else returns 403.

id: string
in path

User ID, email address, or "me".

200 OK

OK — user record.

403 Forbidden

Forbidden — the user is neither the current user nor a colleague.

404 Not Found

Not Found — user does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "locale": "en_GB",
  "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
  "url": "https://quire.io/u/john",
  "nameText": "John",
  "nameHtml": "John",
  "name": "John",
  "id": "john",
  "email": "john@gmail.com",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Get a user by OID.

GET /user/{oid}

Returns the full user record for the given OID. A colleague (someone sharing an organization, project or external team with the user) who hasn't authorized this app is returned with only oid, id and the name fields, unless the user granted the app access to contacts. Anyone else returns 403.

oid: string
in path

User OID.

200 OK

OK — user record.

403 Forbidden

Forbidden — the user is neither the current user nor a colleague.

404 Not Found

Not Found — user does not exist.

Response Content-Types: application/json
Response Example (200 OK)
{
  "locale": "en_GB",
  "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
  "url": "https://quire.io/u/john",
  "nameText": "John",
  "nameHtml": "John",
  "name": "John",
  "id": "john",
  "email": "john@gmail.com",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Get all user records.

GET /user/list

Returns all colleagues of the current user if the user granted the app access to contacts. Otherwise, returns only colleagues who also authorized the same app. If the user did not grant contact access and none of the user’s colleagues authorized this app, only the current user is returned. The first record is always the current user.

200 OK

OK — list of user records; first entry is always the current user.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "locale": "en_GB",
    "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
    "url": "https://quire.io/u/john",
    "nameText": "John",
    "nameHtml": "John",
    "name": "John",
    "id": "john",
    "email": "john@gmail.com",
    "website": "https://coolwebsites.com",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  }
]

Get all user records of the given project (by project ID).

GET /user/list/project/id/{projectId}

Returns the members of the specified project, the current user first. External teams' members are left out, except the members of the current user's own external teams. A member who hasn't authorized this app is returned with only oid, id and the name fields, unless the user granted the app access to contacts.

projectId: string
in path

Project ID.

200 OK

OK — list of project members.

403 Forbidden

Forbidden — the user can't access the project, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "locale": "en_GB",
    "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
    "url": "https://quire.io/u/john",
    "nameText": "John",
    "nameHtml": "John",
    "name": "John",
    "id": "john",
    "email": "john@gmail.com",
    "website": "https://coolwebsites.com",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  }
]

Get all user records of the given project (by project OID).

GET /user/list/project/{oid}

Returns the members of the specified project, the current user first. External teams' members are left out, except the members of the current user's own external teams. A member who hasn't authorized this app is returned with only oid, id and the name fields, unless the user granted the app access to contacts.

oid: string
in path

Project OID.

200 OK

OK — list of project members.

403 Forbidden

Forbidden — the user can't access the project, or didn't authorize it for this app.

404 Not Found

Not Found — project does not exist.

Response Content-Types: application/json
Response Example (200 OK)
[
  {
    "locale": "en_GB",
    "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
    "url": "https://quire.io/u/john",
    "nameText": "John",
    "nameHtml": "John",
    "name": "John",
    "id": "john",
    "email": "john@gmail.com",
    "website": "https://coolwebsites.com",
    "description": "This is *cool*!",
    "descriptionText": "This is cool!",
    "descriptionHtml": "This is <i>cool</i>!",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  }
]

Schema Definitions

AddAppvCatBody: object

claimers: string[]

(Optional) Users allowed to request approval in this category.

  • Omit or null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
string
approvers: string[]

(Optional) Users allowed to approve, reject, or request changes in this category.

  • Omit or null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
string
name: string

Display name.

id: string

Category identifier (URL-safe). Must be unique within the project. The identifier "" is reserved for the implicit default category.

Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review",
  "id": "legal"
}

AddFieldBody: object

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(Optional, select only) Options, each an object with name and an optional color — not a plain string. Example: [{"name": "High", "color": "13"}, {"name": "Low"}].

FieldOption
lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

string
editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

string
multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date, number, money, duration, lookup, and formula fields whose resultType resolves to one of those.

FieldConditionFormat
name: string

Unique name for this field. Must be a non-empty string of at most 1,280 characters, and must not contain }, ", or \.

type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "name": "Priority",
  "type": "number"
}

AddTimelogBody: object

end: string

End timestamp (ISO 8601, UTC). Must be on or after start. Sub-second precision is truncated to whole seconds.

user: string

(Optional) User identifier (OID, ID, or email) the log is credited to. Omitted, null, or empty defaults to the authenticated caller. Unknown users return 400 Bad Request.

billable: boolean

(Optional) Whether this log is billable. Omitted or null defaults to true.

note: string

(Optional) Free-form note for the log. Omitted, null, or empty stores no note.

start: string

Start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds.

Example
{
  "end": "2026-04-26T10:30:00Z",
  "user": "john.doe@example.com",
  "billable": true,
  "note": "Pair-programming session",
  "start": "2026-04-26T09:00:00Z"
}

Approval: object

toggledAt: string

Timestamp (UTC, ISO 8601) of the last state transition.

requester: string

OID of the user who originally requested approval. Preserved across subsequent approve / reject / change transitions.

For ID-based access, prefer requesterRef, which returns {oid, id}.

requesterRef: SimpleEntityWithId

Requester as {oid, id} — same shape as ?return=compact. Recommended over requester for callers using ID-based access.

approverRef: SimpleEntityWithId

Approver as {oid, id} — same shape as ?return=compact. Recommended over approver for callers using ID-based access. Present when approver is.

category: string

Identifier of the approval category this approval belongs to. The default category has id "".

approver: string

OID of the user who most recently approved / rejected / requested changes — or, after a revoke rolled that decision back to awaiting, the user who revoked it. Omitted after a request.

For ID-based access, prefer approverRef, which returns {oid, id}.

state: string awaiting, approved, rejected, changes

Current approval state. Derived from the last POST to /task/approve/id/{projectId}/{taskId} (or the OID form):

  • awaiting — request was posted (initial or rolled-back).
  • approved — approve was posted.
  • rejected — reject was posted.
  • changes — change (request-for-changes) was posted.
Example
{
  "toggledAt": "2026-04-24T10:05:00.000Z",
  "requester": "string",
  "requesterRef": {
    "id": "my_id",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "approverRef": "#/definitions/SimpleEntityWithId",
  "category": "legal",
  "approver": "string",
  "state": "awaiting"
}

ApproveTaskBody: object

description: string

Content of the companion comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Required if the body is supplied. The server prepends a <category>: <status> line (status in the authorizing user's language; no category name for the default category) and a blank line before this text, so this field should contain only the human-written message — do not include the header yourself.

pinned: boolean

(Optional) Whether to pin the companion comment on the task. Default: false.

asUser: boolean

(Optional) If true, the comment is attributed to the app rather than the authorizing user ( app-as-user, as the asUser flag on POST /comment). Default: false. Either way, the authorizing user, not the app, follows the task, as for any comment.

Example
{
  "description": "Please tweak the wording.",
  "pinned": false,
  "asUser": false
}

AppvCat: object

name: string

Display name.

id: string

Category identifier (URL-safe). The implicit default category has an empty id.

claimers: string[]

Users allowed to request approval in this category.

  • Omitted from the response: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.

For ID-based access, prefer claimerRefs, which returns {oid, id} pairs.

string
approvers: string[]

Users allowed to approve, reject, or request changes in this category.

  • Omitted from the response: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.

For ID-based access, prefer approverRefs, which returns {oid, id} pairs.

string
claimerRefs: SimpleEntityWithId

Claimers as {oid, id} pairs — same shape as ?return=compact. Recommended over claimers for callers using ID-based access. Tri-state semantics match claimers: omitted = anyone; [] = admins only; list = those specific users.

SimpleEntityWithId
approverRefs: SimpleEntityWithId

Approvers as {oid, id} pairs — same shape as ?return=compact. Recommended over approvers for callers using ID-based access. Tri-state semantics match approvers.

SimpleEntityWithId
createdBy: SimpleIdentity

User who created this category.

createdAt: string

Timestamp (UTC, ISO 8601) when this category was created.

Example
{
  "name": "Legal Review",
  "id": "legal",
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "claimerRefs": [
    {
      "id": "my_id",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "approverRefs": [
    "#/definitions/SimpleEntityWithId"
  ],
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2026-04-24T10:00:00.000Z"
}

Attachment: object

type: integer

Where the attachment is stored: 1 Google Drive, 2 Quire storage, 3 OneDrive, 4 Dropbox, 5 Box.

url: string

Absolute URL of this attachment. A file stored in Quire is under https://quire.io/att/; a file from an external storage, such as Google Drive, links to that service.

length: integer

Size of the attachment in bytes.

name: string

File name of the attachment.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "type": 2,
  "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
  "length": 20000,
  "name": "file.txt",
  "createdBy": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdAt": "2018-12-22T02:06:58.158Z"
}

BulkUpdateTaskItem: object

oid: string

Target task OID. Exactly one of oid / id must be supplied per item; both or neither is rejected with 400. If it doesn't match a live task in the project, the item is skipped and its response slot is null.

id: integer

Target task ID, an integer; a "#42" string works too. Exactly one of oid / id must be supplied per item; both or neither is rejected with 400. If it doesn't match a live task in the project, the item is skipped and its response slot is null.

description: string

(Optional) New task description. An embedded data: image is rejected — upload the image as an attachment instead.

tags: string[]

(Optional) Tags to replace the current tags on this task (OID or name). This replaces all existing tags. To modify incrementally, use addTags or removeTags. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

string
partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, is rejected with 400. The API can't remove it: null is rejected too.

addTags: string[]

(Optional) Tags to add to this task (OID or name). Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

string
removeTags: string[]

(Optional) Tags to remove from this task (OID or name). Tag names are case-insensitive. An unknown tag is rejected with 400.

string
addAssignees: string[]

(Optional) Assignees to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include all assignees of the parent task

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

string
removeAssignees: string[]

(Optional) Assignees to remove (OID, ID, or email).

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

string
addFollowers: string[]

(Optional) Followers to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
removeFollowers: string[]

(Optional) Followers to remove (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": remove followers that were inherited from the parent task
  • "app": the application

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
addSuccessors: string[]

(Optional) Successors to add (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
removeSuccessors: string[]

(Optional) Successors to remove (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
assignees: string[]

(Optional) Assignees to replace the current assignees (OID, ID, or email). This replaces all existing assignees. To modify incrementally, use addAssignees or removeAssignees.

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

string
start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
  • null clears it. It is rejected if the task is recurring, since a recurring task always has a due; pass recurrence: null in the same request to stop repeating and clear the due together.
recurrence: Recurrence

(Optional) Makes the task repeat, replacing its current recurrence, if any. null stops it repeating.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If the task has none and due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo: object

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely (task and subtasks).
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Undo previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

section: boolean

(Optional) true makes this task a section; false makes it a normal task. If both section and milestone are sent, only section is applied.

milestone: boolean

(Optional) true makes this task a milestone; false makes it a normal task. Ignored if section is sent too.

asUser: boolean

(Optional) If true, marks this update as performed by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (updated by the authorizing user). In bulk-update, each item has its own.

followers: string[]

(Optional) Followers to replace the current followers (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
successors: string[]

(Optional) Successors to replace the current successors (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted); send an entry back unchanged to keep that file.
  • Multi-value (fields configured with multiple: true): provide a list. Pass null to clear the field.

A field you can't view or edit (the definition's viewMembers and editMembers) is rejected with 400; locked stops editing in Quire only, not through the API.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

(Optional) New task name.

status: integer

(Optional) New status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Specify 100 to complete the task. Completion may be rejected (409 Conflict) when project settings require all predecessors to be completed first, or require an approval to be granted.

etc: integer

(Optional) Estimated time to complete, in seconds. Must be 0 to 864,000,000 (10,000 days) or null. Specify null to clear the value.

priority: integer -1, 0, 1, 2

(Optional) New priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.)

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
  • It replaces the stored object as a whole: keys you leave out are removed, and null removes sourceRef. Another app may have stored its own key on the task; to keep it, read the task first and send that key back.
Example
{
  "oid": "iuRRiKoyrxdBFhFTTo",
  "id": 42,
  "description": "This is a **cool** task.",
  "tags": "[\"urgent\", \"design\"]",
  "partner": "UI design team",
  "addTags": "[\"urgent\"]",
  "removeTags": "[\"draft\"]",
  "addAssignees": "[\"me\"]",
  "removeAssignees": "[\"alice@example.com\"]",
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "addSuccessors": "[\"#13\"]",
  "removeSuccessors": "[\"#13\"]",
  "assignees": "[\"me\", \"alice@example.com\"]",
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": "true",
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": "[\"bob@example.com\"]",
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "New idea",
  "status": 100,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}

Change: object

task: string

OID of the task to include or exclude. A task is skipped if it doesn't exist, if it isn't under the sublist's owner, or, for a sublist shared with an external team, if it isn't shared with that team.

single: boolean

Whether the operation applies only to the specified task. Default: false — the task and all its descendants are included or excluded, and earlier includes or excludes of its descendants are cleared. With true, only the task itself changes; its subtasks keep their current state.

exclude: boolean

Whether to exclude the task. Default: false (include).

Example
{
  "task": "2MmYOpJH_ZLeehIjjytH1Rwr",
  "single": false,
  "exclude": false
}

Chat: object

url: string

URL of this chat on the Quire website.

nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Display name (Markdown supported).

id: string

ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

partner: SimpleTaggingEntity

External team this record is shared with. Omitted if none.

archivedAt: string

Timestamp (UTC, ISO 8601) when this record was archived. Omitted if not archived.

mutes: SimpleIdentity

The list of users who have muted this chat channel and will not receive notifications about it.

SimpleIdentity
followers: SimpleIdentity

The list of users following this chat channel.

SimpleIdentity
members: SimpleIdentity

Users who can see this record, and the only ones it is shown to.

  • null — every member of the owner can see it; private tells whether guests and the visitors of a public project or of a share link can too.
  • [] — only the owner's admins can.
  • a list — only those users can.

All three are returned explicitly, so the states can be told apart. Set it when creating the record; it cannot be changed afterwards.

SimpleIdentity
private: boolean

Whether this record is hidden from guests and from the visitors of a public project or of a share link, like a custom field's private. Present only when members is null and partner is null — the one case where it is a choice. A record shared with an external team, with selected members or with the admins only is always hidden from them.

owner: ChatOwner

Project this chat channel belongs to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/w/my_project?chat=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

ChatOwner: object

url: string

URL of this owner on the Quire website.

type: string

Type of the owner: Project, Organization, Folder, or Lot (a smart folder).

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/prj_id",
  "type": "Project",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Comment: object

oid: string

Object identifier (OID), a UUID-like unique string.

description: string

Comment content (Markdown supported).

descriptionText: string

Comment content with Markdown removed.

descriptionHtml: string

Comment content rendered as an HTML fragment converted from Markdown.

attachments: Attachment

Attachments associated with this comment.

Attachment
emojis: CommentEmoji

Emoji reactions to this comment, in the order they were first added. Omitted if none. To add or remove the caller's reactions, use POST /comment/add-emoji/{commentOid}/{emojis} and DELETE /comment/remove-emoji/{commentOid}/{emojis}.

CommentEmoji
url: string

URL of this comment on the Quire website.

pinBy: SimpleIdentity

User who pinned this comment. Omitted if not pinned.

editedAt: string

Timestamp (UTC, ISO 8601) when this comment was last edited. Omitted if never edited.

pinAt: string

Timestamp (UTC, ISO 8601) when this comment was pinned. Omitted if not pinned.

editedBy: SimpleIdentity

User who last edited this comment. Omitted if never edited.

owner: CommentOwner

Task or chat channel this comment was added to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "description": "It is *cool*!",
  "descriptionText": "It is cool!",
  "descriptionHtml": "It is <i>cool</i>!",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "emojis": [
    {
      "emoji": "👍",
      "users": [
        "#/definitions/SimpleIdentity"
      ]
    }
  ],
  "url": "string",
  "pinBy": "#/definitions/SimpleIdentity",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "pinAt": "2018-12-22T02:06:58.158Z",
  "editedBy": "#/definitions/SimpleIdentity",
  "owner": {
    "url": "https://quire.io/w/my_project/42",
    "id": "42",
    "type": "Task",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

CommentEmoji: object

An emoji reaction to a comment, with the users who reacted with it.

emoji: string

The emoji, as a Unicode character. To add or remove it, pass this character or its name (see Emojis) to POST /comment/add-emoji/{commentOid}/{emojis} or DELETE /comment/remove-emoji/{commentOid}/{emojis}.

users: SimpleIdentity

Users who reacted with this emoji.

SimpleIdentity
Example
{
  "emoji": "👍",
  "users": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ]
}

CommentOwner: object

url: string

URL of this owner on the Quire website.

id: object

ID of the owner: for a task, its ID (an integer, unique within its project); for a chat channel, its ID (a string).

type: string Task, Chat

Type of the owner: Task or Chat.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/my_project/42",
  "id": "42",
  "type": "Task",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

CreateChatBody: object

followers: string[]

(Optional) Users (OID, ID, or email) who follow this chat channel. Only those listed follow it, so include "me" for the current user to follow.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
string
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

string
Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}

CreateCommentBody: object

description: string

Content of the new comment (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether to pin this comment. Default: false.

asUser: boolean

(Optional) If true, marks this comment as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). Either way, the authorizing user, not the app, follows the task or chat commented on.

Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}

CreateDashboardBody: object

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

string
Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}

CreateDocBody: object

followers: string[]

(Optional) Users (OID, ID, or email) who follow this document. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.
string
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

string
Example
{
  "followers": "[\"me\"]",
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}

CreateInsightBody: object

description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

string
Example
{
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "members": "[\"me\", \"john\"]"
}

CreateNotificationBody: object

url: string

(Optional) URL associated with the message. When provided, the client may render the message as a hyperlink.

A javascript: URL is rejected with 400. Without a scheme, such as example.com/sync, https:// is assumed; a path starting with / points into Quire.

recipients: string[]

(Optional) Recipients of the notification (OID, ID, or email of a user). Omit or send an empty list to notify only the authorizing user (default).

Each entry must be the authorizing user or a colleague visible to this app — exactly the set returned by GET /user/list. Entries that do not exist or are not visible are rejected with 404 Not Found; the response is identical regardless of the reason, so this endpoint cannot be used to probe whether a user exists.

Special value:

  • ["*"] — broadcast to every user visible to this app (same set as GET /user/list, including the authorizing user). * must be the sole entry; mixing it with other entries returns 400 Bad Request.

Rate-limit cost: one unit per 10 recipients, rounded up (at least 1), counted after * is expanded. A call made once the caller's per-minute or per-hour API budget is used up is rejected with 429 Too Many Requests and no notification is sent.

string
message: string

Notification message. Required; an empty one is rejected with 400.

Example
{
  "url": "https://superheros.com/sync",
  "recipients": "[\"bob@example.com\"]",
  "message": "Unable to synchronize"
}

CreateReminderBody: object

when: string

When this reminder fires (UTC, ISO 8601). A plain instant — there is no all-day reminder, so a bare date is midnight UTC.

Required for a reminder that has no task, or whose task has neither a start nor a due date.

Rejected with 400 when the task already has a start or due date: the reminder then fires from the task's own schedule, and a when of its own would be ignored. Send leads alone in that case.

recurrence: Recurrence

(Optional) How this reminder repeats; when is the first occurrence.

Rejected with 400 on a reminder whose task has a start or due date — it then repeats with its task's schedule, so a rule of its own would be ignored.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Omit it for a single notification at the fire time, which is the default ([{"minutes": 0}]).

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

ReminderLead
name: string

(Optional) Text to show instead of the default message. Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

partner: string

(Optional) OID of the external team to share this reminder with; it then reaches every member of the project and of that team.

Only a project's reminder can carry one, and it cannot be combined with a members list ([] included) — both are 400. Without a task, it must be one of the project's external teams (400 otherwise). On a reminder attached to a task, it must be the team the task is shared with — the task's partner, or the nearest parent task's if it has none — or be omitted; any other value, and any value for a task not shared with a team, is 400.

An external team member shares a reminder with every member only through their own team. With members null, they must set partner to one of their teams; on a reminder attached to a task, that is the task's team. Otherwise 400 says what to send, as it does for a team of the project that isn't theirs.

Sharing with a team is part of Shared reminders, which needs the Premium plan or above (402 otherwise). Settable only when creating the reminder.

members: string[]

(Optional) Users who can see this reminder, and the only ones it notifies. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field — only the authenticated user. This is the default, except with partner: then every member of the project and of that team.
  • Pass null — every member of the owner. An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins.
  • Pass a list — only those users.

Unlike a work's members, omitting the field does not mean every member: pass null explicitly for that.

Omitting it without partner, or naming only yourself (such as ["me"]), keeps the reminder yours; anything else shares it — the Shared reminders feature, which needs the Premium plan or above (402 otherwise).

Rejected with 400 when a listed user is not a member of the owner, when a non-empty list does not include the authenticated user, or when partner is also set. On a reminder attached to a task, every listed user must also be able to see the task (400 naming those who can't): a project member sees every task, but an external team member only the tasks shared with their team. A guest sees only the reminders naming them, and creates none (403: a reminder takes write access).

Settable only when creating the reminder. It cannot be changed afterwards, so recreate the reminder to change who can see it. A personal reminder (created under -) is always its owner's alone, so no one else can be named.

string
Example
{
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill**",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "members": "[\"me\", \"john\"]"
}

CreateStatusBody: object

color: string

(Optional) Status color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

name: string

Display name of the status.

value: integer

Non-negative integer indicating progress. Must be unique within its context (e.g., project); a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually.

Example
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

CreateSublistBody: object

all: boolean

(Optional) Whether every task belongs to the sublist by default. Default: false — only the tasks in includes are in it, with their subtasks. With true, every task of the owner is in it; leave tasks out afterwards by updating the sublist with changes ("exclude": true). Settable only when creating the sublist.

includes: string[]

(Optional) List of task OIDs to include in this sublist. All descendants of the specified tasks will be included as well.

string
description: string

(Optional) Description of the record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image identifier, one of the listed values.

name: string

Display name of the record (Markdown supported).

id: string

(Optional) ID for this record, unique among the owner's records of the same kind (e.g. a project's sublists). If omitted or invalid, Quire derives one from name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

partner: string

(Optional) OID of the external team to share this record with; it is then shared with the members of the project and of that team, and is always private.

Only a project's record can carry one — an organization, a folder or a smart folder has no external team — and it must be one of the project's external teams; any other value is 400. It cannot be combined with members either (400).

An external team member shares a record with every member only through their own team: with members omitted or null, they must set partner to one of their teams. Otherwise 400 names their teams, as it does for a team of the project that isn't theirs.

Settable only when creating the record.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; defaults to false (everyone). Otherwise it is always true: a record shared with an external team, with selected members or with the admins only is hidden from them, so false is rejected with 400.

start: string

(Optional) Target start date: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

members: string[]

(Optional) Users who can see this record, and the only ones it is shown to. Each entry is a user ID, OID, or email, or "me" for the authenticated user.

  • Omit the field, or pass null — every member of the owner can see it, and so can guests and the visitors of a public project or of a share link unless private. This is the default. (A reminder differs: omitting its members means only the authenticated user.) An external team member must also set partner to one of their teams.
  • Pass [] — only the owner's admins can see it.
  • Pass a list — only those users can see it.

Rejected with 400 when:

  • a listed user is not a member of the owner. Unlike a task's assignees, which silently drops a non-member, this is an error: dropping the last one would leave [], which means something else entirely.
  • the list is non-empty and does not include the authenticated user — you would not be able to see what you just created.
  • partner is also set, since an external-team record is already shared with all members of the project and of the team.

Settable only when creating the record. It cannot be changed afterwards, so recreate the record to change who can see it.

string
Example
{
  "all": false,
  "includes": [
    "string"
  ],
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "name": "Highlight 101",
  "id": "Highlight101",
  "partner": "rcBHBYXZSiyDRrHrWPutatfF",
  "private": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "members": "[\"me\", \"john\"]"
}

CreateTagBody: object

color: string

(Optional) Tag color index from Quire’s predefined palette. If omitted, a color will be generated automatically. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

global: boolean

(Optional) Whether this tag is global (available in all projects of the project's organization). If omitted, the tag is not global. true requires the right to manage the organization's tags; otherwise 403.

name: string

Display name of the tag.

Example
{
  "color": "35",
  "global": true,
  "name": "Later"
}

CreateTaskBody: object

description: string

(Optional) A description of the task. An embedded data: image is rejected — upload the image as an attachment instead.

tasks: CreateTaskBody

(Optional) List of subtasks to create along with this task. Each one, at any depth, costs 1 rate-limit unit and counts toward the per-call cap of 300 tasks and the plan's per-minute limit; see Rate Limits.

CreateTaskBody
tags: string[]

(Optional) A list of tag OIDs or names to be added to the new task. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

string
partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, such as null, is rejected with 400.

assignees: string[]

(Optional) A list of user identifiers (OID, ID, or email) to assign this task to.

  • Use "me" to indicate the current user.
  • Use "inherit" to include all assignees of the parent task.

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

string
start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
recurrence: Recurrence

(Optional) Makes the task repeat. Omit it for a task that doesn't repeat.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely.
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Cancel previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

Default: false.

section: boolean

(Optional) Whether this task is a section. Default: false.

milestone: boolean

(Optional) Whether this task is a milestone. Default: false.

asUser: boolean

(Optional) If true, marks this task as created by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (created by the authorizing user). In bulk-add, each item has its own. A nested task's asUser must match its top-level task's (a tree is created by one author); otherwise the call is rejected with 400.

followers: string[]

(Optional) List of user identifiers (OID, ID, or email) who follow this task. Only those listed, and anyone @mentioned in the description, follow it, so include "me" for the current user to follow.

  • Use "me" for the current user.
  • Use "inherit" to include followers of the parent task.
  • Use "app" for the application itself to follow (receive notifications).

For app followers, additional syntaxes are supported:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).
string
successors: string[]

(Optional) List of successor task identifiers (OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted).
  • Multi-value (fields configured with multiple: true): provide a list.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

The name of the task.

status: integer

(Optional) Task status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Default: 0.

etc: integer

(Optional) Estimated time to complete, in seconds: an integer from 0 to 864,000,000 (10,000 days). null is the same as leaving it out.

priority: integer -1, 0, 1, 2

(Optional) Task priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.) Default: 0 (Medium).

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
Example
{
  "description": "This is a *cool* task.",
  "tasks": [
    {
      "description": "This is a *cool* task.",
      "tasks": [
        "#/definitions/CreateTaskBody"
      ],
      "tags": [
        "X6nmx9XjEO2wKbqeB1pRT43C"
      ],
      "partner": "UI design team",
      "assignees": [
        "6QMKkEPBVWETLWrXqws94ALU"
      ],
      "start": "2026-05-01",
      "due": "2026-05-10T17:00Z",
      "recurrence": {
        "byweekday": "[1,3]",
        "byweekno": 2,
        "bydayno": 25,
        "bymonth": 10,
        "dupsubtasks": false,
        "sincelatest": true,
        "freq": "weekly",
        "interval": 1,
        "until": "2020-12-22"
      },
      "peekaboo": true,
      "section": true,
      "milestone": true,
      "asUser": true,
      "followers": [
        "tzufRLqCnud74dARyDSvjWDl"
      ],
      "successors": "[\"#13\"]",
      "yourField": "object",
      "name": "Design new **logo**",
      "status": 0,
      "etc": 0,
      "priority": 0,
      "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
    }
  ],
  "tags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "partner": "UI design team",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": "#/definitions/Recurrence",
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "Design new **logo**",
  "status": 0,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}

Dashboard: object

url: string

URL of this dashboard on the Quire website.

nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Display name (Markdown supported).

id: string

ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

partner: SimpleTaggingEntity

External team this record is shared with. Omitted if none.

archivedAt: string

Timestamp (UTC, ISO 8601) when this record was archived. Omitted if not archived.

members: SimpleIdentity

Users who can see this record, and the only ones it is shown to.

  • null — every member of the owner can see it; private tells whether guests and the visitors of a public project or of a share link can too.
  • [] — only the owner's admins can.
  • a list — only those users can.

All three are returned explicitly, so the states can be told apart. Set it when creating the record; it cannot be changed afterwards.

SimpleIdentity
private: boolean

Whether this record is hidden from guests and from the visitors of a public project or of a share link, like a custom field's private. Present only when members is null and partner is null — the one case where it is a choice. A record shared with an external team, with selected members or with the admins only is always hidden from them.

owner: DashboardOwner

Owner this dashboard belongs to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/w/my_project?dashboard=Board101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

DashboardOwner: object

url: string

URL of this owner on the Quire website.

type: string

Type of the owner: Project, Organization, Folder, or Lot (a smart folder).

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/prj_id",
  "type": "Project",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Doc: object

url: string

URL of this document on the Quire website.

nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Display name (Markdown supported).

id: string

ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

partner: SimpleTaggingEntity

External team this record is shared with. Omitted if none.

archivedAt: string

Timestamp (UTC, ISO 8601) when this record was archived. Omitted if not archived.

mutes: SimpleIdentity

The list of users who have muted this document and will not receive notifications about it.

SimpleIdentity
followers: SimpleIdentity

The list of users following this document.

SimpleIdentity
members: SimpleIdentity

Users who can see this record, and the only ones it is shown to.

  • null — every member of the owner can see it; private tells whether guests and the visitors of a public project or of a share link can too.
  • [] — only the owner's admins can.
  • a list — only those users can.

All three are returned explicitly, so the states can be told apart. Set it when creating the record; it cannot be changed afterwards.

SimpleIdentity
private: boolean

Whether this record is hidden from guests and from the visitors of a public project or of a share link, like a custom field's private. Present only when members is null and partner is null — the one case where it is a choice. A record shared with an external team, with selected members or with the admins only is always hidden from them.

owner: DocOwner

Owner this document belongs to: a project, organization, folder, or smart folder.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/w/my_project?doc=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "mutes": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "members": [
    "#/definitions/SimpleIdentity"
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

DocOwner: object

url: string

URL of this owner on the Quire website.

type: string

Type of the owner: Project, Organization, Folder, or Lot (a smart folder).

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/prj_id",
  "type": "Project",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

ErrorResponse: object

Represents an error response.

code: integer

The error code: the HTTP status, echoed — such as 400, 404, 408 or 409 — except these, which tell apart cases that share a status:

  • 469: a plan quota or limit has been reached (HTTP 402).
  • 470: the subscription has expired (HTTP 402).
  • 471: temporarily blocked; try again later (HTTP 403).
  • 100: the Authorization header is missing or malformed (HTTP 403).
message: string

Human-readable error message.

Example
{
  "code": 429,
  "message": "Something went wrong."
}

FieldConditionFormat: object

color: string

Palette color index. Format: two digits [0-5][0-7] (first = row 0-5, second = column 0-7). Examples: 00, 13, 57. NOT a CSS hex color.

second: Number

(Value fields, between/notBetween only) Second operand. For duration, must be an integer number of seconds.

op: string >=, >, <=, <, =, !=, between, notBetween

(Value fields) Comparison operator.

when: string past, yesterday, today, tomorrow, upcoming, last7d, next7d, lastWeek, thisWeek, nextWeek

(Date fields) Date condition.

first: Number

(Value fields) First operand. For duration, must be an integer number of seconds.

Example
{
  "color": "42",
  "second": "200",
  "op": ">=",
  "when": "today",
  "first": "#/definitions/Number"
}

FieldDefinition: object

private: boolean

(Optional) Whether guests and the visitors of a public project or of a share link can't view this field and its values. Present only when viewMembers is absent, the one case where it is a choice; with viewMembers, the field is always hidden from them.

currency: string

(Optional, money or formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(select only) Option list.

FieldOption
lookup: object

(lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers. Example: {"abc123": 1, "def456": 2}.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: SimpleIdentity

(Optional) The users who can view this field's values; an admin not named sees the definition, not the values. An empty list means the admins only. Absent means everyone private allows. The API returns only the fields the caller can view, and only their values on a task.

SimpleIdentity
editMembers: SimpleIdentity

(Optional) The users who can edit the values; an admin not named can't. An empty list means the admins only. Absent means anyone who can edit the task. Editing also requires viewing the field. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

SimpleIdentity
multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Whether the values are locked: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration or formula only) Duration display format.

formula: string

(formula only) Formula expression.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date (date rules use when) and to number/money/duration/lookup (value rules use op/first/second). A formula is resolved by its resultType: date → date rules, number/money/duration → value rules.

FieldConditionFormat
type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup.

Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

FieldDefinitionWithName: object

name: string

Field name (equals the name query parameter for update/move, new-name for rename, or the name supplied in the body for add).

private: boolean

(Optional) Whether guests and the visitors of a public project or of a share link can't view this field and its values. Present only when viewMembers is absent, the one case where it is a choice; with viewMembers, the field is always hidden from them.

currency: string

(Optional, money or formula only) Currency symbol. When omitted on a money field, defaults to $.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: FieldOption

(select only) Option list.

FieldOption
lookup: object

(lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity (e.g. user OIDs when lookupType=User). Values are numbers. Example: {"abc123": 1, "def456": 2}.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: SimpleIdentity

(Optional) The users who can view this field's values; an admin not named sees the definition, not the values. An empty list means the admins only. Absent means everyone private allows. The API returns only the fields the caller can view, and only their values on a task.

SimpleIdentity
editMembers: SimpleIdentity

(Optional) The users who can edit the values; an admin not named can't. An empty list means the admins only. Absent means anyone who can edit the task. Editing also requires viewing the field. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

SimpleIdentity
multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Whether the values are locked: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration or formula only) Duration display format.

formula: string

(formula only) Formula expression.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys. Default: User.

conditionFormat: FieldConditionFormat

(Optional) Conditional-format rules. Applicable to date (date rules use when) and to number/money/duration/lookup (value rules use op/first/second). A formula is resolved by its resultType: date → date rules, number/money/duration → value rules.

FieldConditionFormat
type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

Field type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup.

Example
{
  "name": "Priority",
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[{\"oid\":\"iDsPd.QP_qM.hN.Trymukn8b\",\"id\":\"john\",\"name\":\"John\"}]",
  "editMembers": "[]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

FieldOption: object

color: string

(Optional) Palette color index for the option's chip. Format: two digits [0-5][0-7] (first = row 0-5, second = column 0-7). Examples: 00, 13, 57. NOT a CSS hex color. If omitted on creation, a color is auto-assigned.

name: string

Option name, unique within the field, and at most 1,280 characters; otherwise 400.

Example
{
  "color": "13",
  "name": "High"
}

Insight: object

url: string

URL of this insight view on the Quire website.

nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Display name (Markdown supported).

id: string

ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

partner: SimpleTaggingEntity

External team this record is shared with. Omitted if none.

archivedAt: string

Timestamp (UTC, ISO 8601) when this record was archived. Omitted if not archived.

members: SimpleIdentity

Users who can see this record, and the only ones it is shown to.

  • null — every member of the owner can see it; private tells whether guests and the visitors of a public project or of a share link can too.
  • [] — only the owner's admins can.
  • a list — only those users can.

All three are returned explicitly, so the states can be told apart. Set it when creating the record; it cannot be changed afterwards.

SimpleIdentity
private: boolean

Whether this record is hidden from guests and from the visitors of a public project or of a share link, like a custom field's private. Present only when members is null and partner is null — the one case where it is a choice. A record shared with an external team, with selected members or with the admins only is always hidden from them.

fields: object

Custom-field definitions for this insight view, keyed by field name. Use the add-field, update-field, remove-field, rename-field, and move-field extensions to mutate entries.

owner: InsightOwner

Owner this insight belongs to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/w/my_project?insight=View101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "fields": "object",
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

InsightOwner: object

url: string

URL of this owner on the Quire website.

type: string

Type of the owner: Project, Organization, Folder, or Lot (a smart folder).

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/prj_id",
  "type": "Project",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Number: object

Example
"object"

Organization: object

url: string

URL of this organization on the Quire website.

email: string

Organization email address.

nameText: string

Organization name with Markdown removed.

nameHtml: string

Organization name rendered as an HTML fragment converted from Markdown.

name: string

Display name of the organization (Markdown supported).

id: string

Organization ID.

website: string

Website URL.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

editedAt: string

Timestamp (UTC, ISO 8601) when this record was last edited.

followers: SimpleIdentity

Users who follow this organization.

SimpleIdentity
createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

OrganizationWithPlan: object

url: string

URL of this organization on the Quire website.

email: string

Organization email address.

nameText: string

Organization name with Markdown removed.

nameHtml: string

Organization name rendered as an HTML fragment converted from Markdown.

name: string

Display name of the organization (Markdown supported).

id: string

Organization ID.

website: string

Website URL.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

subscription: Subscription

Subscription details for this organization.

editedAt: string

Timestamp (UTC, ISO 8601) when this record was last edited.

followers: SimpleIdentity

Users who follow this organization.

SimpleIdentity
createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/c/my_organization",
  "email": "info@company.com",
  "nameText": "My Organization",
  "nameHtml": "My Organization",
  "name": "My Organization",
  "id": "my_organization",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "editedAt": "2018-12-22T02:06:58.158Z",
  "followers": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Partner: object

name: string

Display name of the external team.

color: string

Color index from Quire’s predefined color palette. Two-digit code where the first digit is 0–5 and the second digit is 0–7 (e.g., 35). The palette is available in Quire’s color picker.

oid: string

Object identifier (OID), a UUID-like unique string.

image: string

Image URL representing this team.

project: SimpleIdentity

The project this external team belongs to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "name": "UI design team",
  "color": "35",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Project: object

activeCount: integer

Number of active (not completed) tasks in this project.

taskCount: integer

Total number of tasks in this project.

url: string

URL of this project on the Quire website.

organization: SimpleIdentity

Organization this project belongs to.

nameText: string

Project name with Markdown removed.

nameHtml: string

Project name rendered as an HTML fragment converted from Markdown.

rootCount: integer

Number of root (top-level) tasks in this project.

name: string

Display name of the project (Markdown supported).

id: string

Project ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

archivedAt: string

Timestamp (UTC, ISO 8601) when this project was archived (peekaboo). Omitted if not archived.

start: string

Target start date for this project, yyyy-MM-dd. Omitted if not set.

due: string

Target due date for this project, yyyy-MM-dd. Omitted if not set.

editedAt: string

Timestamp (UTC, ISO 8601) when this record was last edited.

publicAt: string

Timestamp (UTC, ISO 8601) when this project was made public. Omitted if not public.

attachments: Attachment

Attachments associated with this project.

Attachment
followers: SimpleIdentity

Users who follow this project.

SimpleIdentity
approvalCategories: AppvCat

Approval categories defined on this project. Use the add-appv-cat, update-appv-cat, and remove-appv-cat extensions to mutate entries. Null when only the implicit default category is in effect.

AppvCat
fields: object

Custom-field definitions for this project, keyed by field name. Use the add-field, update-field, remove-field, rename-field, and move-field extensions to mutate entries.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

ProjectJsonMap: object

A project exported as JSON. Besides the keys below, it carries the project's own settings, such as description, fields, states, followers and createdAt.

version: string

Version of the export format.

tasks: object[]

Root tasks matching ?status=. Each carries its subtasks under tasks, and its comments and reminders.

object
object
tags: object[]

The project's tags, and its organization's global tags.

object
object
users: object[]

The users the export refers to, such as members, creators and assignees.

object
object
oid: string

Object identifier (OID), a UUID-like unique string.

partners: object[]

The project's external teams. Omitted when the user is in an external team.

object
object
reminders: object[]

The project's reminders that aren't on a task; a task's reminders are under that task. Omitted if none.

object
object
sublists: object[]

The project's sublists.

object
object
docs: object[]

The project's documents.

object
object
chats: object[]

The project's chats, each with its comments.

object
object
insights: object[]

The project's insights.

object
object
dashboards: object[]

The project's dashboards.

object
object
name: string

Display name of the project.

id: string

Project ID.

members: string[]

OIDs of the project's members.

string
Example
{
  "version": "9.0.0",
  "tasks": [
    "object"
  ],
  "tags": [
    "object"
  ],
  "users": [
    "object"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partners": [
    "object"
  ],
  "reminders": [
    "object"
  ],
  "sublists": [
    "object"
  ],
  "docs": [
    "object"
  ],
  "chats": [
    "object"
  ],
  "insights": [
    "object"
  ],
  "dashboards": [
    "object"
  ],
  "name": "My Project",
  "id": "My_Project",
  "members": [
    "string"
  ]
}

ProjectWithPlan: object

activeCount: integer

Number of active (not completed) tasks in this project.

taskCount: integer

Total number of tasks in this project.

url: string

URL of this project on the Quire website.

organization: SimpleIdentity

Organization this project belongs to.

nameText: string

Project name with Markdown removed.

nameHtml: string

Project name rendered as an HTML fragment converted from Markdown.

rootCount: integer

Number of root (top-level) tasks in this project.

name: string

Display name of the project (Markdown supported).

id: string

Project ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

subscription: Subscription

Subscription details for this project.

archivedAt: string

Timestamp (UTC, ISO 8601) when this project was archived (peekaboo). Omitted if not archived.

start: string

Target start date for this project, yyyy-MM-dd. Omitted if not set.

due: string

Target due date for this project, yyyy-MM-dd. Omitted if not set.

editedAt: string

Timestamp (UTC, ISO 8601) when this record was last edited.

publicAt: string

Timestamp (UTC, ISO 8601) when this project was made public. Omitted if not public.

attachments: Attachment

Attachments associated with this project.

Attachment
followers: SimpleIdentity

Users who follow this project.

SimpleIdentity
approvalCategories: AppvCat

Approval categories defined on this project. Use the add-appv-cat, update-appv-cat, and remove-appv-cat extensions to mutate entries. Null when only the implicit default category is in effect.

AppvCat
fields: object

Custom-field definitions for this project, keyed by field name. Use the add-field, update-field, remove-field, rename-field, and move-field extensions to mutate entries.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "activeCount": 20,
  "taskCount": 30,
  "url": "https://quire.io/w/my_project",
  "organization": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "nameText": "My Project",
  "nameHtml": "My Project",
  "rootCount": 5,
  "name": "My Project",
  "id": "my_project",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "subscription": {
    "due": "2038-02-22T02:06:58Z",
    "plan": "Professional",
    "expired": false
  },
  "archivedAt": "2018-12-22T02:06:58.158Z",
  "start": "2024-01-02",
  "due": "2024-05-25",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "publicAt": "2018-12-22T02:06:58.158Z",
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "followers": [
    "#/definitions/SimpleIdentity"
  ],
  "approvalCategories": [
    {
      "name": "Legal Review",
      "id": "legal",
      "claimers": [
        "string"
      ],
      "approvers": [
        "string"
      ],
      "claimerRefs": [
        {
          "id": "my_id",
          "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
        }
      ],
      "approverRefs": [
        "#/definitions/SimpleEntityWithId"
      ],
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2026-04-24T10:00:00.000Z"
    }
  ],
  "fields": "object",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

RateLimit: object

hour: RateLimitBucket

Hourly rate-limit bucket.

minute: RateLimitBucket

Per-minute rate-limit bucket.

organization: string

OID of the organization these limits apply to.

plan: string

The plan whose limits are enforced: Free, Professional, Premium, or Enterprise. During a trial, it is the plan before the trial, not the trial's: a trial doesn't change the rate limits.

Example
{
  "hour": {
    "limit": 1250,
    "remaining": 1208,
    "used": 42,
    "reset": 1774863600
  },
  "minute": "#/definitions/RateLimitBucket",
  "organization": "YxjapXXRCOYxoaiCT4tT3OQm",
  "plan": "Enterprise"
}

RateLimitBucket: object

limit: integer

Maximum number of calls allowed in this window, as enforced: during a trial, that of the plan before the trial. -1 indicates no limit.

remaining: integer

Remaining calls: max(limit - used, 0), or -1 if unlimited.

used: integer

Number of calls consumed so far in the current window.

reset: integer

Unix epoch (seconds) of the next wall-clock boundary at which the used counter will reset.

Example
{
  "limit": 1250,
  "remaining": 1208,
  "used": 42,
  "reset": 1774863600
}

Recurrence: object

byweekday: integer[]

Days of the week, as integers where 0=Mon, 1=Tue, …, 6=Sun.

  • With weekly: required, the days it occurs on, as a list (e.g., [1], [0,3]).
  • With monthly or yearly and byweekno: required, a single integer — the day in that week (e.g., 1 for Tuesday), and returned as one too.

Ignored otherwise.

integer
byweekno: integer

With monthly or yearly: the week of the month, 1–5, or "last" (also 6) for the month's last week. Requires byweekday for the day in that week. If both byweekno and bydayno are given, byweekno wins.

bydayno: integer

With monthly or yearly: the day of the month, 1–31. 31, or "last", means the month's last day, and is returned as 31. Ignored if byweekno is given.

bymonth: integer

With yearly: required, the month, 1–12 (1 = January). Ignored otherwise.

dupsubtasks: boolean

Whether to duplicate subtasks when the task is completed. Default: true.

sincelatest: boolean

With daily: whether to repeat relative to the last completion date. Default: false when omitted or null. Ignored otherwise.

freq: string daily, weekly, monthly, yearly

Recurrence frequency. Besides it:

  • weekly needs byweekday.
  • monthly needs bydayno, or byweekno with byweekday.
  • yearly needs bymonth, plus what monthly needs.

A property that doesn't apply to freq is ignored.

Examples: {"freq": "daily"} repeats every day; {"freq": "weekly", "byweekday": [0, 3]} every Monday and Thursday; {"freq": "monthly", "interval": 2, "byweekno": 2, "byweekday": 1} on the second Tuesday of every other month.

interval: integer

Interval between occurrences, a positive integer. For example, 2 with weekly means every 2 weeks. Default: 1 when omitted or null. 0 or a negative value is 400.

until: string

End date for the recurrence (UTC, ISO 8601). If not specified, the series never ends.

Example
{
  "byweekday": "[1,3]",
  "byweekno": 2,
  "bydayno": 25,
  "bymonth": 10,
  "dupsubtasks": false,
  "sincelatest": true,
  "freq": "weekly",
  "interval": 1,
  "until": "2020-12-22"
}

RecurrenceX: object

seriesId: string

Identifier for the recurrence series this task belongs to. Tasks that share the same seriesId are part of the same recurring series.

byweekday: integer[]

Days of the week, as integers where 0=Mon, 1=Tue, …, 6=Sun.

  • With weekly: required, the days it occurs on, as a list (e.g., [1], [0,3]).
  • With monthly or yearly and byweekno: required, a single integer — the day in that week (e.g., 1 for Tuesday), and returned as one too.

Ignored otherwise.

integer
byweekno: integer

With monthly or yearly: the week of the month, 1–5, or "last" (also 6) for the month's last week. Requires byweekday for the day in that week. If both byweekno and bydayno are given, byweekno wins.

bydayno: integer

With monthly or yearly: the day of the month, 1–31. 31, or "last", means the month's last day, and is returned as 31. Ignored if byweekno is given.

bymonth: integer

With yearly: required, the month, 1–12 (1 = January). Ignored otherwise.

dupsubtasks: boolean

Whether to duplicate subtasks when the task is completed. Default: true.

sincelatest: boolean

With daily: whether to repeat relative to the last completion date. Default: false when omitted or null. Ignored otherwise.

freq: string daily, weekly, monthly, yearly

Recurrence frequency. Besides it:

  • weekly needs byweekday.
  • monthly needs bydayno, or byweekno with byweekday.
  • yearly needs bymonth, plus what monthly needs.

A property that doesn't apply to freq is ignored.

Examples: {"freq": "daily"} repeats every day; {"freq": "weekly", "byweekday": [0, 3]} every Monday and Thursday; {"freq": "monthly", "interval": 2, "byweekno": 2, "byweekday": 1} on the second Tuesday of every other month.

interval: integer

Interval between occurrences, a positive integer. For example, 2 with weekly means every 2 weeks. Default: 1 when omitted or null. 0 or a negative value is 400.

until: string

End date for the recurrence (UTC, ISO 8601). If not specified, the series never ends.

Example
{
  "seriesId": "j47xvxul26",
  "byweekday": "[1,3]",
  "byweekno": 2,
  "bydayno": 25,
  "bymonth": 10,
  "dupsubtasks": false,
  "sincelatest": true,
  "freq": "weekly",
  "interval": 1,
  "until": "2020-12-22"
}

Reminder: object

oid: string

Object identifier (OID), a UUID-like unique string.

task: ReminderTask

Task this reminder is attached to. Omitted if it stands on its own. A reminder cannot be moved to another task.

Only oid, id, name and url are returned here; fetch the task itself for its dates.

when: string

When this reminder fires, if it fires at a time of its own (UTC, ISO 8601).

Omitted whenever task has a start or due date: the reminder then fires from that date instead, and leads counts back from it. The dates are not part of this response, so to show when a reminder will fire, fetch its task and use its due date, or its start date if it has no due date.

recurrence: RecurrenceX

How this reminder repeats. Omitted if it does not repeat, which is always so while the reminder is anchored: it then repeats with its task's own schedule.

leads: ReminderLead

When to notify before the fire time, one notification each. [{"minutes": 0}] means a single notification at the fire time, and is what a reminder created without leads has.

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

ReminderLead
nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Text shown instead of the default message (Markdown supported). Omitted when the default is used, and so are nameText and nameHtml.

partner: SimpleTaggingEntity

External team this reminder is shared with. Omitted if none. When set, it reaches every member of the project and of that team.

members: SimpleIdentity

Users who can see this reminder, and the only ones it notifies.

  • null — every member of the owner.
  • [] — only the owner's admins.
  • a list — only those users.

All three are returned explicitly, so the states can be told apart. Set it when creating the reminder; it cannot be changed afterwards.

SimpleIdentity
owner: ReminderOwner

Project, organization, folder or smart folder this reminder belongs to. Fixed when the reminder is created: a reminder on a task always belongs to that task's project, and one created under - belongs to its creator's My Tasks.

url: string

URL of the page this reminder is shown on.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "oid": "iDsPd.QP_qM.hN.Trymukn8b",
  "task": {
    "url": "https://quire.io/w/my_project/42",
    "id": 42,
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "when": "2027-01-15T09:00:00.000Z",
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "nameText": "Pay the bill",
  "nameHtml": "Pay the <strong>bill</strong>",
  "name": "Pay the **bill**",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "owner": {
    "type": "Project",
    "url": "https://quire.io/w/prj_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "url": "https://quire.io/w/my_project?reminder=iDsPd.QP_qM.hN.Trymukn8b",
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

ReminderLead: object

minutes: integer

How many minutes before the fire time to notify — an absolute offset, so 30 stays 30 real minutes wherever the clocks move in between.

Exactly one of minutes and days must be given. An hour is simply 60 minutes: there is no hours, and a lead is stored and returned in whichever of the two forms it was sent.

days: integer

How many calendar days before the fire time to notify. Unlike minutes, this counts days, not 24-hour spans, so a lead spanning a daylight-saving transition still notifies at the same wall-clock time.

Exactly one of minutes and days must be given. A week is simply 7 days: there is no weeks.

at: string

(Optional, and only with days) The time of day to notify at, as HH:mm on a 24-hour clock — "09:00", "23:30". A 12-hour clock is rejected with 400.

Omit it to notify at the fire time's own time of day, which then follows that time if it later moves.

The clock is read in the time zone of the member who created the reminder, since one notification serves its whole audience and some one zone has to be chosen.

Example
{
  "minutes": 30,
  "days": 1,
  "at": "09:00"
}

ReminderOwner: object

type: string

Kind of the owner: Project, Organization, Folder or Lot (a smart folder). A personal reminder reports Project — it belongs to its creator's My Tasks, which is a project.

url: string

URL of this owner on the Quire website.

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "type": "Project",
  "url": "https://quire.io/w/prj_id",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

ReminderTask: object

url: string

URL of this task on the Quire website.

id: integer

Task ID, unique within its project.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/my_project/42",
  "id": 42,
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

SimpleAttachment: object

url: string

Absolute URL of this attachment. A file stored in Quire is under https://quire.io/att/; a file from an external storage, such as Google Drive, links to that service.

length: integer

Size of the attachment in bytes.

name: string

File name of the attachment.

Example
{
  "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
  "length": 20000,
  "name": "file.txt"
}

SimpleEntityWithId: object

id: string

Identifier for this record.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "id": "my_id",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

SimpleIdentity: object

url: string

URL of this record on the Quire website.

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/u/my_id",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

SimpleTaggingEntity: object

color: string

Color index from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35). The palette appears in Quire’s color picker.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "color": "35",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Status: object

color: string

Color index from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35).

name: string

Display name of the status.

value: integer

Non-negative integer indicating progress. Must be unique within its context (e.g., project). Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually.

Example
{
  "color": "35",
  "name": "Doing",
  "value": 50
}

StorageEntries: object

Stored entries as one JSON object: each key maps to its value, as it was stored. At most 20 entries, by key ascending; {} if none.

Example: {"latest": {"project": "my_project"}, "theme": "dark"}.

Example
"object"

StorageValue: object

A stored value: any JSON value, such as an object, array, string or number, at most 4 KiB as JSON. GET /storage/{name} returns it exactly as PUT /storage/{name} stored it.

Example: after PUT /storage/latest with the body {"project": "my_project"}, GET /storage/latest returns {"project": "my_project"}.

Example
"object"

Sublist: object

url: string

URL of this sublist on the Quire website.

nameText: string

Name with Markdown removed.

nameHtml: string

Name rendered as an HTML fragment converted from Markdown.

name: string

Display name (Markdown supported).

id: string

ID.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

partner: SimpleTaggingEntity

External team this record is shared with. Omitted if none.

all: boolean

Whether every task belongs to this sublist by default. If true, every task of the owner is in it except the excluded ones (with their subtasks); if false, only the included tasks are, with their subtasks.

start: string

Target start date for this record, yyyy-MM-dd. Omitted if not set.

due: string

Target due date for this record, yyyy-MM-dd. Omitted if not set.

archivedAt: string

Timestamp (UTC, ISO 8601) when this record was archived. Omitted if not archived.

members: SimpleIdentity

Users who can see this record, and the only ones it is shown to.

  • null — every member of the owner can see it; private tells whether guests and the visitors of a public project or of a share link can too.
  • [] — only the owner's admins can.
  • a list — only those users can.

All three are returned explicitly, so the states can be told apart. Set it when creating the record; it cannot be changed afterwards.

SimpleIdentity
private: boolean

Whether this record is hidden from guests and from the visitors of a public project or of a share link, like a custom field's private. Present only when members is null and partner is null — the one case where it is a choice. A record shared with an external team, with selected members or with the admins only is always hidden from them.

owner: SublistOwner

Owner this sublist belongs to: a project, organization, folder, or smart folder.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "url": "https://quire.io/w/my_project?sublist=Highlight101",
  "nameText": "Highlight 101",
  "nameHtml": "Highlight 101",
  "name": "Highlight 101",
  "id": "Highlight101",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "partner": {
    "color": "35",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "all": false,
  "start": "2024-01-02",
  "due": "2024-05-25",
  "archivedAt": "2020-02-22T02:06:58.158Z",
  "members": [
    {
      "url": "https://quire.io/u/my_id",
      "id": "my_id",
      "iconColor": "37",
      "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "private": true,
  "owner": {
    "url": "https://quire.io/w/prj_id",
    "type": "Project",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

SublistOwner: object

url: string

URL of this owner on the Quire website.

type: string

Type of the owner: Project, Organization, Folder, or Lot (a smart folder).

id: string

Identifier for this record.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

name: string

Display name.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "url": "https://quire.io/w/prj_id",
  "type": "Project",
  "id": "my_id",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "name": "Foo",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Subscription: object

due: string

Subscription due/renewal timestamp in UTC (ISO 8601).

plan: string

Plan name (e.g., Free, Professional, Premium, Enterprise).

expired: boolean

Whether the subscription is expired. Available only when a due date is present.

Example
{
  "due": "2038-02-22T02:06:58Z",
  "plan": "Professional",
  "expired": false
}

Tag: object

global: boolean

Whether this tag is global (available across projects). May be omitted in responses when false.

color: string

Color index from Quire’s predefined color palette. Two-digit code where the first digit is 0–5 and the second digit is 0–7 (e.g., 35). The palette is available in Quire’s color picker.

name: string

Display name of the tag.

oid: string

Object identifier (OID), a UUID-like unique string.

project: SimpleIdentity

The project this tag belongs to.

createdBy: SimpleIdentity

User who created this record.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "global": true,
  "color": "35",
  "name": "Later",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "project": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "createdBy": "#/definitions/SimpleIdentity",
  "createdAt": "2018-12-22T02:06:58.158Z"
}

Task: object

tags: SimpleTaggingEntity

Tags applied to this task.

SimpleTaggingEntity
successors: string[]

IDs of tasks that depend on this task, as #<id> strings. Omitted if none.

For ID-based access, prefer successorRefs, which returns {oid, id} pairs.

string
predecessors: string[]

IDs of tasks that this task depends on, as #<id> strings. Omitted if none.

For ID-based access, prefer predecessorRefs, which returns {oid, id} pairs.

string
successorRefs: TaskRef

Successors as {oid, id} pairs — same shape as ?return=compact. Recommended over successors for callers using ID-based access.

TaskRef
predecessorRefs: TaskRef

Predecessors as {oid, id} pairs — same shape as ?return=compact. Recommended over predecessors for callers using ID-based access.

TaskRef
oid: string

Object identifier (OID), a UUID-like unique string.

id: integer

Task id.

nameText: string

Task name with Markdown removed.

nameHtml: string

Task name rendered as an HTML fragment converted from Markdown.

name: string

Task name (Markdown supported).

description: string

Task description (Markdown supported).

descriptionText: string

Task description with Markdown removed.

descriptionHtml: string

Task description rendered as an HTML fragment converted from Markdown.

timelogs: Timelog

The time log entries associated with this task. Omitted for a guest member, and for a non-member of a public project, when the project hides time logs from guests (its default).

Timelog
etc: integer

The estimated time to complete the task, expressed in seconds. Omitted if no estimate has been specified.

recurrence: RecurrenceX

Contains the recurrence details of this task. Omitted if the task does not repeat.

status: TaskStatus

Task status as {value, name, color}, e.g. {"value": 0, "name": "To-do", "color": "50"}. A value of 100 or more means the task is completed.

start: string

Start date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-01T09:30Z). Omitted if not set.

due: string

Due date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-10T17:00Z). Omitted if not set.

priority: TaskPriority

Task priority as {value, name}, e.g. {"value": 0, "name": "Medium"}: -1 Low, 0 Medium, 1 High, 2 Urgent.

partner: SimpleTaggingEntity

The external team to which this task belongs. Omitted if this task is not associated with any external team.

assignors: TaskUser

A list of users who assigned this task, each as {oid, id, name}. Each item in assignors corresponds by index to the matching item in assignees (e.g., the first assignee was assigned by the first assignor).

TaskUser
partnerBy: TaskUser

The user who assigned this task to the external team, as {oid, id, name}. If null, the task is not associated with any external team.

assignees: TaskUser

Users assigned to this task, each as {oid, id, name}.

TaskUser
order: integer

Indicates the display order of this task in the board view. A smaller value means the task appears earlier. This field is only relevant in board view and has no meaning elsewhere.

attachments: Attachment

The list of files attached to this task.

Attachment
cover: string

The ID of the attachment used as the cover image for this task.

childCount: integer

The number of subtasks belonging to this task. List them with GET /task/list/id/{projectId}/{taskId} (or GET /task/list/{oid}).

peekaboo: boolean

true if the task is archived (hidden by peekaboo); omitted otherwise.

section: boolean

true if this task is a section; omitted otherwise.

milestone: boolean

true if this task is a milestone; omitted otherwise.

url: string

URL of this task on the Quire website.

mutes: TaskUser

The list of users who have muted this task and will not receive notifications about it, even if they are assigned. Each as {oid, id, name}.

TaskUser
followers: TaskUser

The list of users who are following this task, each as {oid, id, name}.

TaskUser
favorites: TaskUser

The list of users who have marked this task as a favorite, each as {oid, id, name}.

TaskUser
sourceRef: object

The JSON object an app stored with the task, as is; omitted if none. Its text, if any, is the Markdown Quire shows as the task's source line; other keys are the app's own data. Find tasks by one of its keys with the search endpoints' ?source-ref=<key>.

toggledAt: string

The timestamp of the most recent status change for this task.

toggledBy: TaskUser

The user who last changed the status of this task, as {oid, id, name}.

editedAt: string

Represents the timestamp of the most recent edit to this record.

commentedAt: string

Indicates the timestamp of the most recent comment posted on this record.

Omitted if the record has never had a comment.

Since comments can be removed, this value may not always match the current set of comments.

approval: Approval

The task's current approval state. Omitted if no approval has been requested. Mutate via POST /task/approve/id/{projectId}/{taskId} (request / approve / reject / change) and DELETE /task/revoke-approval/id/{projectId}/{taskId} (cancel), or their OID forms POST /task/approve/{oid} and DELETE /task/revoke-approval/{oid}.

archivedAt: string

When the task was archived (hidden by peekaboo). Omitted if it isn't archived.

archivedBy: TaskUser

The user who archived the task, as {oid, id, name}. null or omitted if it isn't archived.

reshowAt: string

When an archived task shows again: set if it was hidden for a number of days or until a time (peekaboo with a positive integer or a date/time string). Omitted otherwise.

yourField: object

PLACEHOLDER — no key is literally named yourField. Each custom field with a value on the task appears as a top-level key named after the field (as defined via /project/add-field), e.g. "Cost": 120. A field you can't view is left out, and so is a field with no value, except a formula, which is always present. Values by field type:

  • Select: a list of option names, e.g. ["High"].
  • User: a list of {oid, id, name}.
  • Task: a list of {oid, id}.
  • Date: yyyy-MM-dd, or yyyy-MM-dd'T'HH:mm:ss'Z' with a time.
  • Duration: a number of seconds.
  • Formula: its computed value.
  • File: a list of attachments, each with an absolute url (as in attachments), plus type and createdAt (epoch milliseconds), which you send back unchanged when you keep a file.
  • Others (Text, Number, Money, Checkbox, Email, Hyperlink, …): the value as set.
createdBy: TaskUser

User who created this task, as {oid, id, name}.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "commentedAt": "2023-12-22T09:06:28.253Z"
}

TaskInfo: object

id: integer

Task id.

oid: string

Object identifier (OID), a UUID-like unique string.

parent: TaskInfo

The parent task as {oid, id, parent}, nested up to 10 ancestors. On the task itself, null if it has no parent; in the chain, the top-level ancestor has no parent key.

Past 10 ancestors, the 10th ancestor's parent is {"parent": "<OID>"}, holding the OID of the 11th, with no oid or id, to mark the cut-off.

Example
{
  "id": 12,
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "parent": {
    "id": 12,
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
    "parent": "#/definitions/TaskInfo"
  }
}

TaskPriority: object

A task's priority: its value and name.

value: integer -1, 0, 1, 2

Priority value: -1 Low, 0 Medium, 1 High, 2 Urgent.

name: string

Name of the priority in the authorizing user's language, e.g. Medium in English.

Example
{
  "value": 0,
  "name": "Medium"
}

TaskRef: object

id: integer

Task id.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "id": 12,
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

TaskStatus: object

A task's status: its value, name, and color.

value: integer

Status value, one of the project's statuses. 0 is the initial status; 100 or more means completed.

name: string

Display name of the status. A built-in status without a custom name gets its default name in the authorizing user's language.

color: string

Palette index for the status color. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 35). Matches the predefined colors shown in Quire’s color picker.

Example
{
  "value": 0,
  "name": "To-do",
  "color": "50"
}

TaskUser: object

A user as a task gives it: {oid, id, name}.

name: string

Display name of the user.

id: string

User ID.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "name": "John Doe",
  "id": "john_doe",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

TaskWithParentInfo: object

tags: SimpleTaggingEntity

Tags applied to this task.

SimpleTaggingEntity
successors: string[]

IDs of tasks that depend on this task, as #<id> strings. Omitted if none.

For ID-based access, prefer successorRefs, which returns {oid, id} pairs.

string
predecessors: string[]

IDs of tasks that this task depends on, as #<id> strings. Omitted if none.

For ID-based access, prefer predecessorRefs, which returns {oid, id} pairs.

string
successorRefs: TaskRef

Successors as {oid, id} pairs — same shape as ?return=compact. Recommended over successors for callers using ID-based access.

TaskRef
predecessorRefs: TaskRef

Predecessors as {oid, id} pairs — same shape as ?return=compact. Recommended over predecessors for callers using ID-based access.

TaskRef
oid: string

Object identifier (OID), a UUID-like unique string.

id: integer

Task id.

nameText: string

Task name with Markdown removed.

nameHtml: string

Task name rendered as an HTML fragment converted from Markdown.

name: string

Task name (Markdown supported).

description: string

Task description (Markdown supported).

descriptionText: string

Task description with Markdown removed.

descriptionHtml: string

Task description rendered as an HTML fragment converted from Markdown.

timelogs: Timelog

The time log entries associated with this task. Omitted for a guest member, and for a non-member of a public project, when the project hides time logs from guests (its default).

Timelog
etc: integer

The estimated time to complete the task, expressed in seconds. Omitted if no estimate has been specified.

recurrence: RecurrenceX

Contains the recurrence details of this task. Omitted if the task does not repeat.

status: TaskStatus

Task status as {value, name, color}, e.g. {"value": 0, "name": "To-do", "color": "50"}. A value of 100 or more means the task is completed.

start: string

Start date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-01T09:30Z). Omitted if not set.

due: string

Due date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-10T17:00Z). Omitted if not set.

priority: TaskPriority

Task priority as {value, name}, e.g. {"value": 0, "name": "Medium"}: -1 Low, 0 Medium, 1 High, 2 Urgent.

partner: SimpleTaggingEntity

The external team to which this task belongs. Omitted if this task is not associated with any external team.

assignors: TaskUser

A list of users who assigned this task, each as {oid, id, name}. Each item in assignors corresponds by index to the matching item in assignees (e.g., the first assignee was assigned by the first assignor).

TaskUser
partnerBy: TaskUser

The user who assigned this task to the external team, as {oid, id, name}. If null, the task is not associated with any external team.

assignees: TaskUser

Users assigned to this task, each as {oid, id, name}.

TaskUser
order: integer

Indicates the display order of this task in the board view. A smaller value means the task appears earlier. This field is only relevant in board view and has no meaning elsewhere.

attachments: Attachment

The list of files attached to this task.

Attachment
cover: string

The ID of the attachment used as the cover image for this task.

childCount: integer

The number of subtasks belonging to this task. List them with GET /task/list/id/{projectId}/{taskId} (or GET /task/list/{oid}).

peekaboo: boolean

true if the task is archived (hidden by peekaboo); omitted otherwise.

section: boolean

true if this task is a section; omitted otherwise.

milestone: boolean

true if this task is a milestone; omitted otherwise.

url: string

URL of this task on the Quire website.

mutes: TaskUser

The list of users who have muted this task and will not receive notifications about it, even if they are assigned. Each as {oid, id, name}.

TaskUser
followers: TaskUser

The list of users who are following this task, each as {oid, id, name}.

TaskUser
favorites: TaskUser

The list of users who have marked this task as a favorite, each as {oid, id, name}.

TaskUser
sourceRef: object

The JSON object an app stored with the task, as is; omitted if none. Its text, if any, is the Markdown Quire shows as the task's source line; other keys are the app's own data. Find tasks by one of its keys with the search endpoints' ?source-ref=<key>.

toggledAt: string

The timestamp of the most recent status change for this task.

toggledBy: TaskUser

The user who last changed the status of this task, as {oid, id, name}.

editedAt: string

Represents the timestamp of the most recent edit to this record.

commentedAt: string

Indicates the timestamp of the most recent comment posted on this record.

Omitted if the record has never had a comment.

Since comments can be removed, this value may not always match the current set of comments.

approval: Approval

The task's current approval state. Omitted if no approval has been requested. Mutate via POST /task/approve/id/{projectId}/{taskId} (request / approve / reject / change) and DELETE /task/revoke-approval/id/{projectId}/{taskId} (cancel), or their OID forms POST /task/approve/{oid} and DELETE /task/revoke-approval/{oid}.

archivedAt: string

When the task was archived (hidden by peekaboo). Omitted if it isn't archived.

archivedBy: TaskUser

The user who archived the task, as {oid, id, name}. null or omitted if it isn't archived.

reshowAt: string

When an archived task shows again: set if it was hidden for a number of days or until a time (peekaboo with a positive integer or a date/time string). Omitted otherwise.

parent: TaskInfo

The parent task as {oid, id, parent}, nested up to 10 ancestors. On the task itself, null if it has no parent; in the chain, the top-level ancestor has no parent key.

Past 10 ancestors, the 10th ancestor's parent is {"parent": "<OID>"}, holding the OID of the 11th, with no oid or id, to mark the cut-off.

yourField: object

PLACEHOLDER — no key is literally named yourField. Each custom field with a value on the task appears as a top-level key named after the field (as defined via /project/add-field), e.g. "Cost": 120. A field you can't view is left out, and so is a field with no value, except a formula, which is always present. Values by field type:

  • Select: a list of option names, e.g. ["High"].
  • User: a list of {oid, id, name}.
  • Task: a list of {oid, id}.
  • Date: yyyy-MM-dd, or yyyy-MM-dd'T'HH:mm:ss'Z' with a time.
  • Duration: a number of seconds.
  • Formula: its computed value.
  • File: a list of attachments, each with an absolute url (as in attachments), plus type and createdAt (epoch milliseconds), which you send back unchanged when you keep a file.
  • Others (Text, Number, Money, Checkbox, Email, Hyperlink, …): the value as set.
createdBy: TaskUser

User who created this task, as {oid, id, name}.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "commentedAt": "2023-12-22T09:06:28.253Z"
}

TaskWithProjectParentInfo: object

tags: SimpleTaggingEntity

Tags applied to this task.

SimpleTaggingEntity
successors: string[]

IDs of tasks that depend on this task, as #<id> strings. Omitted if none.

For ID-based access, prefer successorRefs, which returns {oid, id} pairs.

string
predecessors: string[]

IDs of tasks that this task depends on, as #<id> strings. Omitted if none.

For ID-based access, prefer predecessorRefs, which returns {oid, id} pairs.

string
successorRefs: TaskRef

Successors as {oid, id} pairs — same shape as ?return=compact. Recommended over successors for callers using ID-based access.

TaskRef
predecessorRefs: TaskRef

Predecessors as {oid, id} pairs — same shape as ?return=compact. Recommended over predecessors for callers using ID-based access.

TaskRef
oid: string

Object identifier (OID), a UUID-like unique string.

id: integer

Task id.

nameText: string

Task name with Markdown removed.

nameHtml: string

Task name rendered as an HTML fragment converted from Markdown.

name: string

Task name (Markdown supported).

description: string

Task description (Markdown supported).

descriptionText: string

Task description with Markdown removed.

descriptionHtml: string

Task description rendered as an HTML fragment converted from Markdown.

timelogs: Timelog

The time log entries associated with this task. Omitted for a guest member, and for a non-member of a public project, when the project hides time logs from guests (its default).

Timelog
etc: integer

The estimated time to complete the task, expressed in seconds. Omitted if no estimate has been specified.

recurrence: RecurrenceX

Contains the recurrence details of this task. Omitted if the task does not repeat.

status: TaskStatus

Task status as {value, name, color}, e.g. {"value": 0, "name": "To-do", "color": "50"}. A value of 100 or more means the task is completed.

start: string

Start date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-01T09:30Z). Omitted if not set.

due: string

Due date, in UTC: yyyy-MM-dd for a date without a time, or yyyy-MM-dd'T'HH:mm'Z' with one (e.g. 2026-05-10T17:00Z). Omitted if not set.

priority: TaskPriority

Task priority as {value, name}, e.g. {"value": 0, "name": "Medium"}: -1 Low, 0 Medium, 1 High, 2 Urgent.

partner: SimpleTaggingEntity

The external team to which this task belongs. Omitted if this task is not associated with any external team.

assignors: TaskUser

A list of users who assigned this task, each as {oid, id, name}. Each item in assignors corresponds by index to the matching item in assignees (e.g., the first assignee was assigned by the first assignor).

TaskUser
partnerBy: TaskUser

The user who assigned this task to the external team, as {oid, id, name}. If null, the task is not associated with any external team.

assignees: TaskUser

Users assigned to this task, each as {oid, id, name}.

TaskUser
order: integer

Indicates the display order of this task in the board view. A smaller value means the task appears earlier. This field is only relevant in board view and has no meaning elsewhere.

attachments: Attachment

The list of files attached to this task.

Attachment
cover: string

The ID of the attachment used as the cover image for this task.

childCount: integer

The number of subtasks belonging to this task. List them with GET /task/list/id/{projectId}/{taskId} (or GET /task/list/{oid}).

peekaboo: boolean

true if the task is archived (hidden by peekaboo); omitted otherwise.

section: boolean

true if this task is a section; omitted otherwise.

milestone: boolean

true if this task is a milestone; omitted otherwise.

url: string

URL of this task on the Quire website.

mutes: TaskUser

The list of users who have muted this task and will not receive notifications about it, even if they are assigned. Each as {oid, id, name}.

TaskUser
followers: TaskUser

The list of users who are following this task, each as {oid, id, name}.

TaskUser
favorites: TaskUser

The list of users who have marked this task as a favorite, each as {oid, id, name}.

TaskUser
sourceRef: object

The JSON object an app stored with the task, as is; omitted if none. Its text, if any, is the Markdown Quire shows as the task's source line; other keys are the app's own data. Find tasks by one of its keys with the search endpoints' ?source-ref=<key>.

toggledAt: string

The timestamp of the most recent status change for this task.

toggledBy: TaskUser

The user who last changed the status of this task, as {oid, id, name}.

editedAt: string

Represents the timestamp of the most recent edit to this record.

commentedAt: string

Indicates the timestamp of the most recent comment posted on this record.

Omitted if the record has never had a comment.

Since comments can be removed, this value may not always match the current set of comments.

approval: Approval

The task's current approval state. Omitted if no approval has been requested. Mutate via POST /task/approve/id/{projectId}/{taskId} (request / approve / reject / change) and DELETE /task/revoke-approval/id/{projectId}/{taskId} (cancel), or their OID forms POST /task/approve/{oid} and DELETE /task/revoke-approval/{oid}.

archivedAt: string

When the task was archived (hidden by peekaboo). Omitted if it isn't archived.

archivedBy: TaskUser

The user who archived the task, as {oid, id, name}. null or omitted if it isn't archived.

reshowAt: string

When an archived task shows again: set if it was hidden for a number of days or until a time (peekaboo with a positive integer or a date/time string). Omitted otherwise.

parent: TaskInfo

The parent task as {oid, id, parent}, nested up to 10 ancestors. On the task itself, null if it has no parent; in the chain, the top-level ancestor has no parent key.

Past 10 ancestors, the 10th ancestor's parent is {"parent": "<OID>"}, holding the OID of the 11th, with no oid or id, to mark the cut-off.

project: SimpleEntityWithId

The project to which this task belongs.

yourField: object

PLACEHOLDER — no key is literally named yourField. Each custom field with a value on the task appears as a top-level key named after the field (as defined via /project/add-field), e.g. "Cost": 120. A field you can't view is left out, and so is a field with no value, except a formula, which is always present. Values by field type:

  • Select: a list of option names, e.g. ["High"].
  • User: a list of {oid, id, name}.
  • Task: a list of {oid, id}.
  • Date: yyyy-MM-dd, or yyyy-MM-dd'T'HH:mm:ss'Z' with a time.
  • Duration: a number of seconds.
  • Formula: its computed value.
  • File: a list of attachments, each with an absolute url (as in attachments), plus type and createdAt (epoch milliseconds), which you send back unchanged when you keep a file.
  • Others (Text, Number, Money, Checkbox, Email, Hyperlink, …): the value as set.
createdBy: TaskUser

User who created this task, as {oid, id, name}.

createdAt: string

Creation timestamp in UTC (ISO 8601).

Example
{
  "tags": [
    {
      "color": "35",
      "name": "Foo",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "successors": "[\"#135\", \"#26\"]",
  "predecessors": "[\"#17\", \"#66\", \"#91\"]",
  "successorRefs": [
    {
      "id": 12,
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "predecessorRefs": [
    "#/definitions/TaskRef"
  ],
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "id": 12,
  "nameText": "Design new logo",
  "nameHtml": "Design new <b>logo</b>",
  "name": "Design new **logo**",
  "description": "This is a *cool* task.",
  "descriptionText": "This is a cool task.",
  "descriptionHtml": "This is a <i>cool</i> task.",
  "timelogs": [
    {
      "start": "2023-02-20T00:00:00.000Z",
      "end": "2023-02-20T00:05:35.000Z",
      "user": {
        "url": "https://quire.io/u/my_id",
        "id": "my_id",
        "iconColor": "37",
        "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
        "name": "Foo",
        "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
      },
      "billable": true,
      "note": "A piece of cake"
    }
  ],
  "etc": 500,
  "recurrence": {
    "seriesId": "j47xvxul26",
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "status": {
    "value": 0,
    "name": "To-do",
    "color": "50"
  },
  "start": "2026-05-01",
  "due": "2026-05-10",
  "priority": {
    "value": 0,
    "name": "Medium"
  },
  "partner": "#/definitions/SimpleTaggingEntity",
  "assignors": [
    {
      "name": "John Doe",
      "id": "john_doe",
      "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
    }
  ],
  "partnerBy": "#/definitions/TaskUser",
  "assignees": [
    "#/definitions/TaskUser"
  ],
  "order": 99,
  "attachments": [
    {
      "type": 2,
      "url": "https://quire.io/att/Ta/sdcQOGgeUtyaFFzb9p0IwAgi/qfqVmUtC/image.png",
      "length": 20000,
      "name": "file.txt",
      "createdBy": "#/definitions/SimpleIdentity",
      "createdAt": "2018-12-22T02:06:58.158Z"
    }
  ],
  "cover": "qfqVmUtC",
  "childCount": 5,
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "url": "https://quire.io/w/my_project/123",
  "mutes": [
    "#/definitions/TaskUser"
  ],
  "followers": [
    "#/definitions/TaskUser"
  ],
  "favorites": [
    "#/definitions/TaskUser"
  ],
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}",
  "toggledAt": "2018-12-22T02:06:58.158Z",
  "toggledBy": "#/definitions/TaskUser",
  "editedAt": "2018-12-22T02:06:58.158Z",
  "commentedAt": "2023-12-22T09:06:28.253Z"
}

Timelog: object

start: string

Start timestamp (UTC) for this time log.

end: string

End timestamp (UTC) for this time log.

user: SimpleIdentity

User who recorded this time log.

billable: boolean

Whether this time log is billable. May be omitted in responses when false.

note: string

Optional note for this time log.

Example
{
  "start": "2023-02-20T00:00:00.000Z",
  "end": "2023-02-20T00:05:35.000Z",
  "user": {
    "url": "https://quire.io/u/my_id",
    "id": "my_id",
    "iconColor": "37",
    "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
    "name": "Foo",
    "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
  },
  "billable": true,
  "note": "A piece of cake"
}

UpdateAppvCatBody: object

claimers: string[]

(Optional) New claimers list — users allowed to request approval in this category.

  • null: anyone can request.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
string
approvers: string[]

(Optional) New approvers list — users allowed to approve, reject, or request changes in this category.

  • null: anyone can respond.
  • [] (empty list): admins only.
  • List of user OIDs: those specific users.
string
name: string

(Optional) New display name.

Example
{
  "claimers": [
    "string"
  ],
  "approvers": [
    "string"
  ],
  "name": "Legal Review"
}

UpdateChatBody: object

Request body for updating a chat channel. Extends UpdateWorkBody and adds follower management; omitted fields preserve existing values.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}

UpdateCommentBody: object

description: string

(Optional) New comment content (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

pinned: boolean

(Optional) Whether the comment is pinned.

asUser: boolean

(Optional) If true, the app, not the authorizing user, is recorded as the one who made this change: editedBy when description is changed, and pinBy when the comment is pinned. Default: false.

Example
{
  "description": "Adjust style",
  "pinned": false,
  "asUser": true
}

UpdateDashboardBody: object

Request body for updating a dashboard. Extends UpdateWorkBody with no additional fields; omitted fields preserve existing values.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}

UpdateDocBody: object

Request body for updating a doc. Extends UpdateWorkBody and adds follower management; omitted fields preserve existing values.

addFollowers: string[]

(Optional) Followers (OID, ID, or email) to add. Adding a user also takes them off mutes.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
removeFollowers: string[]

(Optional) Followers (OID, ID, or email) to remove. A removed user who follows the project is also muted (added to mutes), so they stop getting notifications about it.

Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application.

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
followers: string[]

(Optional) Followers (OID, ID, or email) to replace the current followers. Applies only when the owner is a project; rejected (400) for organization, folder, or smart-folder documents.

  • "me" — the current user.
  • "app" — the application follows (receives notifications).

App follower syntax: app|team, app|team|channel, or app|/path.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Example
{
  "addFollowers": "[\"me\"]",
  "removeFollowers": "[\"bob@example.com\"]",
  "followers": "[\"me\"]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}

UpdateFieldBody: object

private: boolean

(Optional) Hide this field and its values from guests and from the visitors of a public project or of a share link. A choice only without viewMembers; with it, the field is always hidden from them, so false is rejected with 400.

currency: string

(Optional, money/formula only) Currency symbol. Pass $ to reset a money field to its default.

percent: boolean

(Optional, number only) Format the value as a percentage.

options: UpdateFieldOption

(Optional, select only) Replacement option list, each an object with name, an optional color, and an optional from. It replaces the entire set; [] removes every option. To rename an option, give its current name in from, e.g. {"name": "Critical", "from": "High"}; tasks set to it get the new name. Without from, nothing is treated as a rename: a current option that no entry names, in name or from, is removed, and tasks set to it lose that value. An entry without color keeps the current color of the option it matches (by from, else by name).

UpdateFieldOption
lookup: object

(Optional, lookup only) Map from lookup key to numeric value. Keys are OIDs of the configured lookupType entity. Replaces the entire map.

hidden: boolean

(Optional) Hide this field from the task detail panel.

clearOnDup: boolean

(Optional) Clear this field when duplicating a task.

viewMembers: string[]

(Optional) Users who can view this field's values; an admin not named sees the definition, not the values. Each entry is a user ID, OID, or email, or "me" for the authenticated user, and must be a member of the field's owner, an external team's member included. Pass [] for the admins only, or null for everyone private allows.

string
editMembers: string[]

(Optional) Users who can edit the values, in the same form as viewMembers; an admin not named can't. Editing also requires viewing the field. Pass [] for the admins only, or null for anyone who can edit the task. locked stops editing in Quire regardless of this list; the API ignores the lock, so this list still applies to API writes.

string
multiple: boolean

(Optional) Allow multiple values. Applies to select, user, task, and file (always true for file).

locked: boolean

(Optional) Lock the values: no one can edit them in Quire, admins included, while the API still can, e.g., to push values from another system.

withTime: boolean

(Optional, date only) Include time-of-day in addition to the date.

ndecimal: integer -1, 0, 1, 2, 3

(Optional, number/money only) Number of decimal digits. -1 means no rounding.

durationFormat: string hh:mm:ss, hh:mm, 1h1m, 1h, 1d1h, dd:hh:mm:ss, dd:hh:mm, dd:hh

(Optional, duration/formula only) Duration display format.

formula: string

(Optional, formula only) Formula expression, at most 5,120 characters.

resultType: string text, number, money, date, duration, checkbox

(Optional, formula only) Expected result type.

lookupType: string User, Task, Project, Organization

(Optional, lookup only) Source type for lookup keys.

conditionFormat: FieldConditionFormat

(Optional) Replacement conditional-format rules. It replaces the entire list; [] removes every rule.

FieldConditionFormat
type: string text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula, file, lookup

(Optional) Field type. Immutable on update — if supplied, must match the existing field's type. Usually omitted; include only to verify the stored type. A project's field is one of text, number, money, date, duration, select, checkbox, user, task, hyperlink, email, formula and file; an insight's field is formula or lookup. A key for another type, such as options on a number field, returns 400.

Example
{
  "private": false,
  "currency": "USD",
  "percent": false,
  "options": [
    {
      "from": "High",
      "color": "13",
      "name": "High"
    }
  ],
  "lookup": "object",
  "hidden": false,
  "clearOnDup": false,
  "viewMembers": "[\"me\", \"john\"]",
  "editMembers": "[\"me\"]",
  "multiple": true,
  "locked": false,
  "withTime": false,
  "ndecimal": 2,
  "durationFormat": "hh:mm",
  "formula": "SUM(Subtask.Amount)",
  "resultType": "number",
  "lookupType": "User",
  "conditionFormat": [
    {
      "color": "42",
      "second": "200",
      "op": ">=",
      "when": "today",
      "first": "#/definitions/Number"
    }
  ],
  "type": "number"
}

UpdateFieldOption: object

from: string

(Optional) The current name of the option this entry renames to name; tasks set to that option get name instead. Without it, the entry is the current option of the same name, or a new option if there is none. It must name a current option, and no two entries may match the same option (by name or from); otherwise 400.

color: string

(Optional) Palette color index for the option's chip. Format: two digits [0-5][0-7] (first = row 0-5, second = column 0-7). Examples: 00, 13, 57. NOT a CSS hex color. If omitted on creation, a color is auto-assigned.

name: string

Option name, unique within the field, and at most 1,280 characters; otherwise 400.

Example
{
  "from": "High",
  "color": "13",
  "name": "High"
}

UpdateInsightBody: object

Request body for updating an insight view. Extends UpdateWorkBody with no additional fields; omitted fields preserve existing values.

private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Example
{
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}

UpdateOrganizationBody: object

description: string

(Optional) New description for this organization (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead. Needs an admin of the organization.

addFollowers: string[]

(Optional) Followers to add to this organization (OID, ID, or email). Special values:

  • "me": the current user follows the organization
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

string
removeFollowers: string[]

(Optional) Followers to remove from this organization (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

string
followers: string[]

(Optional) Followers to replace the current followers of this organization (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

Needs edit access to the organization, even for only "me": unlike a project, an organization can't be followed with read access.

string
name: string

(Optional) New display name for this organization (Markdown supported). Needs an admin of the organization.

Example
{
  "description": "**Great** organization to start with.",
  "addFollowers": [
    "string"
  ],
  "removeFollowers": [
    "string"
  ],
  "followers": [
    "string"
  ],
  "name": "My Organization"
}

UpdateProjectBody: object

public: boolean

(Optional) Public toggle. Specify true to make this project public; specify false to make it private. Making it public needs a plan with public projects; otherwise 402 (code 469).

description: string

(Optional) New description for this project (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

archived: boolean

(Optional) Archive toggle. Specify true to archive this project; specify false to unarchive.

addFollowers: string[]

(Optional) Followers to add to this project (OID, ID, or email). Special values:

  • "me": the current user follows the project
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL when invoking the registered hook. Example: hook https://super.app/hooks/standard + follower app|/soc1/33456/a7 → https://super.app/hooks/standard/soc1/33456/a7

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

string
removeFollowers: string[]

(Optional) Followers to remove from this project (OID, ID, or email). Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

string
start: string

(Optional) Target start date for this project: a date only, e.g. 2024-01-02; a value with a time of day returns 400. null clears it. Needs a project admin.

due: string

(Optional) Target due date for this project: a date only, e.g. 2024-05-25; a value with a time of day returns 400. null clears it. Needs a project admin.

followers: string[]

(Optional) Followers to replace the current followers of this project (OID, ID, or email). This replaces all existing followers. To modify incrementally, use addFollowers or removeFollowers.

Accepts the same special values as addFollowers: "me" (the current user) and "app" / "app|team" / "app|team|channel" / "app|/path" (the application).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"].

string
name: string

(Optional) New display name for this project (Markdown supported).

Example
{
  "public": true,
  "description": "**Great** project to start with.",
  "archived": true,
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "start": "2024-01-02",
  "due": "2024-05-25",
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "name": "My Project"
}

UpdateReminderBody: object

when: string

(Optional) When this reminder fires (UTC, ISO 8601).

Rejected with 400 on a reminder whose task has a start or due date — it fires from the task's schedule, so a when of its own would be ignored — and also when set to null on one that has no other time to fire from.

recurrence: Recurrence

(Optional) How this reminder repeats; null stops it repeating.

Rejected with 400 on a reminder whose task has a start or due date, for the same reason as when.

leads: ReminderLead

(Optional) When to notify before the fire time, one notification each. Replaces the current list.

Each entry is an object naming exactly one of minutes (an absolute offset) and days (calendar days, so a lead spanning a daylight-saving transition keeps its wall-clock time), the latter taking an optional at clock.

Neither may be negative — a lead counts back from the fire time, and nothing fires after it — nor exceed 10,000 days ahead of it, and there may be at most 30 of them.

ReminderLead
name: string

(Optional) Text to show instead of the default message. Pass null to fall back to the default.

Only inline Markdown applies: **bold**, *italic*, ~~strikethrough~~, `code` and links; anything else, such as a list or a heading, stays literal text. At most 1,280 characters, not counting the markup (400 otherwise).

Example
{
  "when": "2027-03-20T18:30:00.000Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "leads": [
    {
      "minutes": 30,
      "days": 1,
      "at": "09:00"
    }
  ],
  "name": "Pay the **bill** today"
}

UpdateStatusBody: object

color: string

(Optional) Status color index from Quire’s predefined palette (two digits: first 0–5, second 0–7; e.g., 35).

name: string

(Optional) New display name for the status.

value: integer

(Optional) New numeric status value. Non-negative integer indicating progress. Must be unique within the project; a value already in use returns 409. Values ≥ 100 are treated as completed. When listing or searching tasks, ?status=100 (or completed) matches every completed status; values above 100 can't be filtered individually. The value of 0 (the initial status) and 100 (completed) can't change.

Example
{
  "color": "35",
  "name": "Later",
  "value": 50
}

UpdateSublistBody: object

start: string

(Optional) Target start date for this record: a date only, e.g. 2024-01-02; a value with a time of day returns 400.

due: string

(Optional) Target due date for this record: a date only, e.g. 2024-05-25; a value with a time of day returns 400.

changes: Change

(Optional) Tasks to add to or remove from this sublist, applied in order. Each item is {"task": "<task OID>", "exclude": false, "single": false}:

  • exclude: true removes the task instead of adding it.
  • single: true changes only the task itself; by default its subtasks follow it.

A task that doesn't exist is skipped. Example — add one task with its subtasks and leave another out:

[
  {"task": "2MmYOpJH_ZLeehIjjytH1Rwr"},
  {"task": "q8Rn1zX5bKcT0wGvJmLd3PaE", "exclude": true}
]
Change
private: boolean

(Optional) Hide this record from guests and from the visitors of a public project or of a share link, like a custom field's private. A choice only when members is null and partner is null; otherwise it is always true, and false is rejected with 400.

description: string

(Optional) New description for this record (Markdown supported). An embedded data: image is rejected — upload the image as an attachment instead.

iconColor: string

(Optional) Icon color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 37, 57). NOT a CSS hex color.

image: string icon-view-list, icon-view-kanban, icon-grid, icon-view-timeline, icon-calendar, icon-timer, icon-briefcase-o, icon-rocket-o, icon-bug-o, icon-user-o, icon-colleagues-o, icon-lightbulb-o, icon-leaf-o, icon-clapperboard, icon-sitemap-o, icon-list, icon-flash-on-o, icon-piggy-bank-o, icon-graduation-cap-o, icon-paper-plane-o, icon-globe-o, icon-music-o, icon-detail, icon-beach-o, icon-paper, icon-home-o, icon-building, icon-database-o, icon-microscope-o, icon-hamburger-o, icon-trophy-o, icon-thumbs-o-up, icon-thumbs-o-down, icon-smile-o, icon-frown-o, icon-meh-o, icon-bullseye, icon-incomplete, icon-filter-o, icon-comment, icon-view-insight, icon-view-dashboard, icon-square-dotted-o

(Optional) Icon image for this record, one of the listed values.

archived: boolean

(Optional) Archive toggle. Specify true to archive this record; specify false to unarchive.

name: string

(Optional) New display name for this record.

id: string

(Optional) New ID for this record, unique among the owner's records of the same kind. If invalid, Quire derives one from the name; if already taken, Quire changes it by appending characters. Neither is an error, so read the id back from the response.

Example
{
  "start": "2024-01-02",
  "due": "2024-05-25",
  "changes": "[{\"task\": \"2MmYOpJH_ZLeehIjjytH1Rwr\"}, {\"task\": \"q8Rn1zX5bKcT0wGvJmLd3PaE\", \"exclude\": true}]",
  "private": false,
  "description": "**Great** record to start with.",
  "iconColor": "37",
  "image": "icon-view-kanban",
  "archived": true,
  "name": "Highlight 101",
  "id": "Highlight101"
}

UpdateTagBody: object

color: string

(Optional) Tag color index from Quire's predefined palette. Two-digit code [0-5][0-7]: first digit 0-5, second digit 0-7 (e.g. 00, 35, 57). NOT a CSS hex color.

global: boolean

(Optional) Whether the tag is global (available across projects). If set to false, you must also provide project.

project: string

(Optional) Project OID that this tag is limited to. Used only when global is explicitly set to false; ignored otherwise.

name: string

(Optional) New display name for the tag.

Example
{
  "color": "35",
  "global": true,
  "project": "Dyh2YkFcu9uLgLFIeN1kB4Ld",
  "name": "Later"
}

UpdateTaskBody: object

description: string

(Optional) New task description. An embedded data: image is rejected — upload the image as an attachment instead.

tags: string[]

(Optional) Tags to replace the current tags on this task (OID or name). This replaces all existing tags. To modify incrementally, use addTags or removeTags. Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

string
partner: string

(Optional) The external team to share this task with: the name or OID of one of the project's external teams (GET /partner/list/id/{projectId} lists them). The team's members then get access to the task and its subtasks. Setting it takes the right to assign tasks (403 otherwise). A name or OID that matches no team, or a value that isn't a string, is rejected with 400. The API can't remove it: null is rejected too.

addTags: string[]

(Optional) Tags to add to this task (OID or name). Tag names are case-insensitive. Each must be an existing tag of the project, or a global tag of its organization; an unknown tag is rejected with 400, not created.

string
removeTags: string[]

(Optional) Tags to remove from this task (OID or name). Tag names are case-insensitive. An unknown tag is rejected with 400.

string
addAssignees: string[]

(Optional) Assignees to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include all assignees of the parent task

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

string
removeAssignees: string[]

(Optional) Assignees to remove (OID, ID, or email).

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

string
addFollowers: string[]

(Optional) Followers to add (OID, ID, or email). Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
removeFollowers: string[]

(Optional) Followers to remove (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": remove followers that were inherited from the parent task
  • "app": the application

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL.

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
addSuccessors: string[]

(Optional) Successors to add (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
removeSuccessors: string[]

(Optional) Successors to remove (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
assignees: string[]

(Optional) Assignees to replace the current assignees (OID, ID, or email). This replaces all existing assignees. To modify incrementally, use addAssignees or removeAssignees.

Accepts the same special values as addAssignees: "me" (the current user) and "inherit" (all assignees of the parent task).

Only project members (external-team members included) can be assigned; anyone else is silently left out. An unknown user is rejected with 400.

string
start: string

(Optional) Start date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
due: string

(Optional) Due date/time in UTC.

  • With time: yyyy-MM-dd'T'HH:mmZ (e.g., 2020-10-30T09:30Z).
  • Date only: yyyy-MM-dd (e.g., 2020-10-30).

Notes:

  • Seconds are not supported.
  • 2020-10-30T00:00:00 is treated as 2020-10-30 (date only).
  • To specify exactly midnight UTC, use 2020-10-30T00:00 (no seconds).
  • null clears it. It is rejected if the task is recurring, since a recurring task always has a due; pass recurrence: null in the same request to stop repeating and clear the due together.
recurrence: Recurrence

(Optional) Makes the task repeat, replacing its current recurrence, if any. null stops it repeating.

  • freq (required): daily, weekly, monthly, or yearly.
  • interval: a positive integer; 2 with weekly means every 2 weeks. Default: 1.
  • until: end date, e.g. 2026-12-31. Default: never ends.
  • weekly needs byweekday: the days of the week as a list, where 0 = Monday … 6 = Sunday, e.g. [0, 3].
  • monthly needs bydayno, the day of the month (1–31, or "last"), or byweekno, the week of the month (1–5, or "last"), with byweekday as a single day in that week, e.g. 1 for Tuesday. If both byweekno and bydayno are given, byweekno wins.
  • yearly needs bymonth, the month (1–12, 1 = January), plus what monthly needs.
  • dupsubtasks: whether to duplicate subtasks when the task is completed. Default: true.
  • sincelatest: with daily only, whether to repeat from the last completion date. Default: false.

A property that doesn't apply to freq is ignored; an invalid value, or a missing required one, is rejected with 400.

A recurring task always has a due. If the task has none and due is omitted, it is derived from the recurrence: the nearest occurrence since today. The request is rejected if the derived due precedes start; specify due explicitly in that case.

peekaboo:
boolean
integer
string

(Optional) Peekaboo setting. Accepts a boolean, a positive integer, or a date/time string:

  • true: Hide indefinitely (task and subtasks).
  • positive integer up to 10000: Number of days to hide.
  • larger integer: When to show it again, in milliseconds since the epoch (not seconds).
  • date/time string: When to show it again, in UTC, as yyyy-MM-dd'T'HH:mmZ (e.g., 2026-11-04T09:30Z); date only (yyyy-MM-dd) means 6 AM that day in the user's time zone.
  • false: Undo previous peekaboo.

When to show it again must be in the future, otherwise 400. It shows again within the hour after that time.

section: boolean

(Optional) true makes this task a section; false makes it a normal task. If both section and milestone are sent, only section is applied.

milestone: boolean

(Optional) true makes this task a milestone; false makes it a normal task. Ignored if section is sent too.

asUser: boolean

(Optional) If true, marks this update as performed by the app. Read asUser as app-as-user: the app itself is the user, not the authorizing user. Default: false (updated by the authorizing user). In bulk-update, each item has its own.

followers: string[]

(Optional) Followers to replace the current followers (OID, ID, or email).

Special values:

  • "me": the current user
  • "inherit": include followers of the parent task
  • "app": the application follows (receives notifications)

App follower syntax:

  • app|team or app|team|channel
  • app|/path → appended to the hook URL (e.g., .../standard/soc1/33456/a7).

With read access only, addFollowers and removeFollowers may name only yourself: "me", or "app" to add the app on your behalf. Adding or removing anyone else returns 403, even along with yourself. followers replaces every follower, so it needs edit access even as ["me"]. An update that only follows or unfollows doesn't change editedAt.

string
successors: string[]

(Optional) Successors to replace the current successors (task OID or ID).

IDs can be specified as #id or id. Integer IDs are also accepted.

string
yourField: object

PLACEHOLDER — do NOT send a key literally named yourField. Instead, use the custom field's own name (as defined via /project/add-field) as the JSON key, with a value matching the field's type:

  • Text / Email / Hyperlink: string.
  • Number / Money: numeric value (no currency symbol).
  • Checkbox: true or false.
  • Select: option name (string).
  • Date: ISO 8601 timestamp (yyyy-MM-dd'T'HH:mm:ssZ) or date-only (yyyy-MM-dd).
  • Duration: number of seconds.
  • User: user OID, user ID, or email — server resolves to the user's OID.
  • Task: task OID, integer task ID, or #<id> string — server resolves to the task's OID (scoped to this project).
  • File: the attachment list as a task returns it (absolute url accepted); send an entry back unchanged to keep that file.
  • Multi-value (fields configured with multiple: true): provide a list. Pass null to clear the field.

A field you can't view or edit (the definition's viewMembers and editMembers) is rejected with 400; locked stops editing in Quire only, not through the API.

Example body fragment: {"Priority": 3, "Owners": ["alice", "bob@example.com"], "Depends": ["#42"]}.

name: string

(Optional) New task name.

status: integer

(Optional) New status. Must be one of the project's status values (GET /status/list/id/{projectId} lists them); any other value is rejected with 400. Every project has 0, the initial status, and 100, completed; 100 or more means completed. Specify 100 to complete the task. Completion may be rejected (409 Conflict) when project settings require all predecessors to be completed first, or require an approval to be granted.

etc: integer

(Optional) Estimated time to complete, in seconds. Must be 0 to 864,000,000 (10,000 days) or null. Specify null to clear the value.

priority: integer -1, 0, 1, 2

(Optional) New priority: -1 Low, 0 Medium, 1 High, 2 Urgent. (The server also accepts the case-insensitive English names Low, Medium, High, Urgent, but the integer form is recommended for typed callers.)

sourceRef: object

(Optional) A JSON object your app stores with the task, such as where the task came from. Quire keeps it as is and returns it as sourceRef whenever the task is read.

  • text (optional): a Markdown string Quire shows as the task's source line in the task details. Include a link to the source, e.g. Source: [GitHub issue 42](https://github.com/acme/web/issues/42).
  • Any other key: your app's own data, not shown in Quire. Put it under a key named after your app, e.g. github, so it won't clash with another app's.
  • To find these tasks later, search with ?source-ref=github: it returns the tasks whose sourceRef has that key, whatever its value.
  • Size: at most about 2,048 characters, keys and values together, and text must be a string; otherwise 400.
  • It replaces the stored object as a whole: keys you leave out are removed, and null removes sourceRef. Another app may have stored its own key on the task; to keep it, read the task first and send that key back.
Example
{
  "description": "This is a **cool** task.",
  "tags": [
    "ITaVbkhh3iVcEcV3vuSLeE2k"
  ],
  "partner": "UI design team",
  "addTags": [
    "X6nmx9XjEO2wKbqeB1pRT43C"
  ],
  "removeTags": [
    "mPAQrYU1qt8wAYAInKRlTnvl"
  ],
  "addAssignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "removeAssignees": [
    "Job4NSW9xK6Owcke8iKj7zyH"
  ],
  "addFollowers": [
    "sfsvLbDVPvi1QMf2GkDn7VSy"
  ],
  "removeFollowers": [
    "aBuz4MwfZ5CasOae6stnFa2f"
  ],
  "addSuccessors": "[\"#13\"]",
  "removeSuccessors": "[\"#13\"]",
  "assignees": [
    "6QMKkEPBVWETLWrXqws94ALU"
  ],
  "start": "2026-05-01",
  "due": "2026-05-10T17:00Z",
  "recurrence": {
    "byweekday": "[1,3]",
    "byweekno": 2,
    "bydayno": 25,
    "bymonth": 10,
    "dupsubtasks": false,
    "sincelatest": true,
    "freq": "weekly",
    "interval": 1,
    "until": "2020-12-22"
  },
  "peekaboo": true,
  "section": true,
  "milestone": true,
  "asUser": true,
  "followers": [
    "tzufRLqCnud74dARyDSvjWDl",
    "app"
  ],
  "successors": "[\"#13\"]",
  "yourField": "object",
  "name": "New idea",
  "status": 100,
  "etc": 0,
  "priority": 0,
  "sourceRef": "{\"github\": {\"repo\": \"acme/web\", \"issue\": 42}, \"text\": \"Source: [GitHub issue 42](https://github.com/acme/web/issues/42)\"}"
}

UpdateTimelogBody: object

end: string

(Optional) New end timestamp (ISO 8601, UTC). Must be on or after the (new or existing) start. Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

user: string

(Optional) New user the log is credited to (OID, ID, or email). Omit or set null to preserve. Send empty string to reset to the authenticated caller.

billable: boolean

(Optional) New billable flag. Omit or set null to preserve.

note: string

(Optional) New note. Omit or set null to preserve. Send empty string to clear.

start: string

(Optional) New start timestamp (ISO 8601, UTC). Sub-second precision is truncated to whole seconds. Omit or set null to preserve.

Example
{
  "end": "2026-04-26T10:45:00Z",
  "user": "john.doe@example.com",
  "billable": false,
  "note": "Updated note",
  "start": "2026-04-26T09:15:00Z"
}

User: object

locale: string

The locale of the current user. Omitted for other users.

timeZone: object

The time zone of the current user: name, and offset from UTC in minutes. Omitted for other users.

url: string

URL of this user on the Quire website.

nameText: string

User name with Markdown removed.

nameHtml: string

User name rendered as an HTML fragment converted from Markdown.

name: string

Display name of the user (Markdown supported).

id: string

User ID.

email: string

Email address.

website: string

Website URL.

description: string

Description (Markdown supported).

descriptionText: string

Description with Markdown removed.

descriptionHtml: string

Description rendered as an HTML fragment converted from Markdown.

iconColor: string

Color index for the icon from Quire’s predefined palette. Two-digit code: first digit 0–5, second digit 0–7 (e.g., 37).

image: string

Image URL representing this record.

oid: string

Object identifier (OID), a UUID-like unique string.

Example
{
  "locale": "en_GB",
  "timeZone": "{\"offset\": 480, \"name\": \"Asia/Taipei\"}",
  "url": "https://quire.io/u/john",
  "nameText": "John",
  "nameHtml": "John",
  "name": "John",
  "id": "john",
  "email": "john@gmail.com",
  "website": "https://coolwebsites.com",
  "description": "This is *cool*!",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "iconColor": "37",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

Recurring:

byweekday: object
Example
{
  "byweekday": [
    1,
    4
  ]
}