Getting Started
Overview
The GQueues REST API lets you read queues and tasks, and create and update queues and sections, and create, update and delete tasks programmatically. It uses a single versioned endpoint with an action parameter to select the operation.
Beta: This API is in beta. You must activate the beta feature before you can use it. See the Getting Started guide for instructions.
All requests and responses use JSON. The API follows REST conventions: GET for read operations and POST for write operations.
Base URL
All API requests are made to:
The current version is v0 (beta). The version will increment to v1 when the API becomes generally available.
Authentication
Every request must include a valid API access token in the Authorization header using the Bearer scheme:
Authorization: Bearer gq_your_access_token_here
Access tokens are created from the API tab in your GQueues settings. Tokens are prefixed with gq_ and contain 256 bits of entropy.
❗️Please Note: Tokens are shown only once at creation time. Copy and securely store your token before closing the dialog. If a token is compromised, revoke it immediately from Settings.
Authentication Errors
Status | Meaning |
401 | Missing, malformed, expired, or revoked token. Also returned when the API beta is not activated for the account — by design this is indistinguishable from an invalid token. |
403 | Account is not permitted to use the API (e.g. a banned account), or the token lacks the scope required for the requested operation. |
Rate Limits
The API enforces rate limits to ensure fair usage and system stability. Limits are applied at multiple levels:
Per IP address -- protects against burst and sustained abuse from a single source.
Per account -- overall request budget for your account.
Per token -- individual limit for each access token.
Paid subscriptions receive more generous limits than the Lite tier. Write operations like task creation have tighter limits than read operations.
Rate Limit Response
When a limit is exceeded, the API returns 429 with a Retry-After header indicating how many seconds to wait before retrying.
HTTP/1.1 429 Too Many Requests
Retry-After: 62
Content-Type: application/json
{"error": "Rate limit exceeded"}
Best practice: Always respect the Retry-After header. Clients that retry immediately or in tight loops may be subject to longer backoff periods.
Idempotency
All POST (mutating) endpoints require an Idempotency-Key request header. This ensures that retrying a request (e.g. due to a network timeout) does not create duplicate resources.
Idempotency-Key: create-task-abc123
Key Rules
Required on all
POSTrequests. Omitting it returns 400.Max length: 128 characters
Allowed characters:
a-z,A-Z,0-9,_,-,.Scoped per account and endpoint path: Different accounts can reuse the same key without conflict, and the same key used on different
POSTactions will not collide.TTL: How long a cached response stays replayable depends on the action. Create operations (
createTask,createSection,createQueue) cache for 24 hours -- a wide replay window. Update operations (updateTask,deleteTask,updateQueue,updateSection) cache for only 2 minutes -- long enough to absorb an immediate retry, short enough not to mask a later intentional re-edit. After the window expires, the same key can be reused for a new request.Only successful responses are cached. Only
2xxresponses are stored in the idempotency cache. If a request returns a4xxor5xx, the key is not cached and the same key may immediately be reused to retry the request.
Idempotency Behavior
Scenario | Result |
First request with a new key | Processed normally. |
Retry with same key and same body | Cached response replayed. |
Same key but different body | 422 -- key already used with a different payload. |
Concurrent duplicate request | 409 with |
👉 Pro Tip: For automated integrations, generate deterministic keys by hashing the request content (e.g. SHA-256 of the task text). This prevents duplicates even across retries. Use a random UUID only when you intentionally want to create a duplicate.
Error Handling
The API returns errors as JSON objects with an error field and an appropriate HTTP status code.
{
"error": "Missing required parameter: queueKey"
}
Common Error Codes
Status | Meaning |
400 | Bad request -- missing or invalid parameters, malformed JSON, non-object body, unknown action, or Idempotency-Key validation failure (missing header, empty, exceeds 128 characters, or contains invalid characters) |
401 | Unauthorized -- missing, invalid, expired, or revoked token, or the API beta is not activated for the account |
403 | Forbidden -- banned account, the token lacks the required scope, or insufficient queue/category/team permissions |
409 | Conflict -- concurrent duplicate request (idempotency lock held). Response body: |
413 | Payload Too Large -- request body exceeds 64 KB |
415 | Unsupported Media Type -- |
422 | Unprocessable Entity -- idempotency key reused with a different request body |
429 | Too Many Requests -- rate limit exceeded (see |
500 | Internal server error |
Endpoints
The API exposes the following actions on the single /api/v0 endpoint:
Action | Method | Purpose |
| GET | List queues grouped by category. |
| GET | List personal categories. |
| GET | List the teams the account belongs to. |
| GET | List a queue's active or archived tasks. |
| GET | Full-text search tasks across all queues. |
| POST | Create one or more tasks. |
| POST | Update one or more existing tasks. |
| POST | Move one or more tasks to the trash. |
| POST | Add a section to a queue. |
| POST | Create a personal or team queue. |
| GET | List a queue's sections. |
| POST | Rename a queue, or edit its notes or color. |
| POST | Rename a section, or edit its notes or color. |
Get Queues
Returns queues accessible to the authenticated user, grouped by category.
Please Note: This only includes queues where tasks actually live (My Queues, Team Queues, Inbox). Any view that is filtering tasks in your account (Smart Queues and Save Searches) are not included.
GET /v0?action=getQueues
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
| string | No | Comma-separated list of queue categories to return. Valid values: |
Request Headers
Header | Required | Description |
| Yes |
|
Example Request
curl -X GET "https://www.gqueues.com/api/v0?action=getQueues&scope=personal,team" \
-H "Authorization: Bearer gq_your_access_token_here"
Response
Returns a JSON object with keys for each requested scope. Each key maps to an array of queue objects.
{
"personal": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Inbox",
"notes": "",
"numOpen": 12,
"numCompleted": 45,
"isInbox": true,
"dateCreated": "2024-01-15T10:30:00",
"lastModified": "2024-03-20T14:00:00",
"permission": { "view": true, "update": true, "manage": true, "publish": true }
},
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Follow-ups",
"notes": "",
"numOpen": 5,
"numCompleted": 18,
"isInbox": false,
"dateCreated": "2024-02-10T08:00:00",
"lastModified": "2024-03-19T16:45:00",
"categoryName": "Work",
"categoryKey": "ahNzfmdxdWV1ZXMtaHJk...",
"permission": { "view": true, "update": true, "manage": true, "publish": true }
}
],
"team": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Sprint Backlog",
"notes": "Current sprint items",
"numOpen": 8,
"numCompleted": 23,
"isInbox": false,
"isTeamInbox": false,
"dateCreated": "2024-02-01T09:00:00",
"lastModified": "2024-03-18T11:00:00",
"teamName": "Engineering",
"teamKey": "ahNzfmdxdWV1ZXMtaHJk...",
"permission": { "view": true, "update": true, "manage": true, "publish": false }
}
]
}
Queue Object Fields
Field | Type | Description |
| string | Unique identifier for the queue. Use this value as the |
| string | Display name of the queue. |
| string | Queue description or notes, as plain text. Empty string if none. |
| integer | Number of active (non-completed) tasks. |
| integer | Number of completed tasks. |
| boolean |
|
| boolean |
|
| string or null | The queue color, as a CSS class such as |
| boolean | Team queues only. |
| string | Team queues only. Name of the team this queue belongs to. |
| string | Team queues only. Datastore key of the team this queue belongs to. |
| string | Personal queues in a category only. Name of the category. Personal queues with the same |
| string | Personal queues in a category only. Datastore key of the category, emitted alongside |
| string or null | ISO 8601 datetime when the queue was created. |
| string or null | ISO 8601 datetime when the queue was last modified. |
| object | Permissions the authenticated user has on this queue (see below). |
| object | Which of this queue's fields this account may actually change (see below). |
Permission Object
Field | Type | Description |
| boolean | Can view the queue and its tasks. |
| boolean | Can add, edit, and complete tasks. |
| boolean | Can rename, reorder, and delete the queue. |
| boolean | Can share or publish the queue. |
Editable Object
Combines this account's rights with the queue's own restrictions, so a client can predict a refusal instead of discovering it. permission says what the account may do; editable says what it may do to this queue.
Field | Type | Description |
| boolean | Whether Update Queue will accept a rename. |
| boolean | Whether Update Queue will accept a notes edit. |
| boolean | Whether Update Queue will accept a color change. |
| boolean | Whether Create Section and Update Section will accept a change in this queue. Requires update rights. A section already being deleted still refuses, so check |
Get Categories
Returns the account's personal categories (including empty ones), in the account's configured display order. Categories are the top-level groupings that hold personal queues; use a category key as the categoryKey parameter in Create Queue.
GET /api/v0?action=getCategories
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
Example Request
curl -X GET "https://www.gqueues.com/api/v0?action=getCategories" \
-H "Authorization: Bearer gq_your_access_token_here"
Response
{
"categories": [
{ "key": "ahNzfmdxdWV1ZXMtaHJk...", "name": "Work", "order": 0, "numQueues": 4 },
{ "key": "ahNzfmdxdWV1ZXMtaHJk...", "name": "Personal", "order": 1, "numQueues": 2 }
]
}Category Object Fields
Field | Type | Description |
| string | The category's datastore key. |
| string | The category name. |
| integer | The category's position in the account's ordering (0-based). |
| integer | Number of queues in the category. |
Get Teams
Returns the teams the account belongs to (including teams with zero queues), in the account's configured order. Returns an empty list when the account is not permitted to use teams. Use a team key as the teamKey parameter in Create Queue.
GET /api/v0?action=getTeams
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
Example Request
curl -X GET "https://www.gqueues.com/api/v0?action=getTeams" \
-H "Authorization: Bearer gq_your_access_token_here"
Response
{
"teams": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Engineering",
"access": "manager",
"numQueues": 7,
"canCreateQueues": true
}
]
}
Team Object Fields
Field | Type | Description |
| string | The team's datastore key. |
| string | The team name. |
| string | The account's access level on this team (e.g. |
| integer | Number of queues in the team. |
| boolean | Whether the account may create queues in this team ( |
Get Sections
Returns a queue's sections, in the order they appear in the queue.
GET /api/v0?action=getSections
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Datastore key of the queue whose sections to list. Maximum 500 characters. The account must be authorized to view it. |
Request Headers
Header | Required | Description |
| Yes |
|
Example Request
curl "https://www.gqueues.com/api/v0?action=getSections&queueKey=ahNzfmdxdWV1ZXMtaHJk..." \
-H "Authorization: Bearer gq_your_access_token_here"
Response
{
"sections": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"sectionId": "sec-1a2b3c",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "This Week",
"color": "gq-queue-bkgnd-8",
"notes": "Time-sensitive items",
"position": "00000000",
"isBeingDeleted": false,
"collapsedByDefault": false
}
]
}
Section Object Fields
Field | Type | Description |
| string | The section's datastore key. Use this value as the |
| string | The section's stable client-side identifier. |
| string | Datastore key of the queue the section belongs to. |
| string | The section name, as plain text. |
| string or null | The section color (CSS class), or |
| string or null | The section notes, as plain text. |
| string | The section's ordering position within the queue. |
| boolean |
|
| boolean | Whether the section renders collapsed on first view. |
Please Note: Sections being deleted are returned rather than filtered out, so a client can tell the difference between a section that is going away and one that never existed. Unlike the sections array in List Tasks, this response contains only real sections -- there is no synthetic "(No Section)" bucket.
Please Note: When the queue does not exist or the account is not authorized to view it, the response is 403 with a masked error message (the same message for not-found and not-authorized, so callers cannot probe which keys exist).
List Tasks
Returns the tasks in a single queue with pagination support. By default it returns the queue's active tasks grouped into sections; pass filter=archived to return the queue's archived (completed) tasks instead.
Please Note: This action was previously named getActiveTasks. The old name is no longer supported.
GET /v0?action=listTasks
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Datastore key of the queue to list. The account must be authorized to view it. A key that does not resolve and a key naming a queue the account cannot view both return the same masked 403, so callers cannot probe which keys exist. |
| string | No | Which task states to return. Defaults to |
| integer | No | Maximum number of top-level tasks per page. Default: |
| string | No | Pagination offset (a non-negative integer, as returned in a prior response's |
Request Headers
Header | Required | Description |
| Yes |
|
Example Request
curl -X GET "https://www.gqueues.com/api/v0?action=listTasks&queueKey=ahNzfm...&filter=active,snoozed&limit=50" \
-H "Authorization: Bearer gq_your_access_token_here""
To list the queue's archived tasks instead:
curl -X GET "https://www.gqueues.com/api/v0?action=listTasks&queueKey=ahNzfm...&filter=archived&limit=50" \
-H "Authorization: Bearer gq_your_access_token_here"
Response
Returns a paginated list of tasks. For the active/snoozed filter, the response also includes section information; the sections array is omitted when filter=archived.
{
"items": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"title": "Draft the quarterly report",
"notes": "Include revenue and churn.",
"completed": false,
"crossed": false,
"tags": ["reports", "q3"],
"position": "00000000_0001",
"queueName": "Work",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"numComments": 0,
"hasSubitems": false,
"attachments": [],
"access": "user",
"addComments": true,
"assignments": [],
"link": "https://app.gqueues.com/main/task/active/5629499534213120-6207617754725632",
"sectionKey": "ahNzfmdxdWV1ZXMtaHJk...",
"dueDate": {
"dueDate": "Fri, August 15",
"duration": null,
"rawDate": "2025-08-15",
"title": "Fri, August 15 @ 9:00 AM",
"text": "Aug 15 @ 9:00 AM",
"repeats": false
},
"schedule": {
"dueDate": { "local": "2025-08-15T09:00:00", "tz": "America/New_York" },
"dueTime": true
},
"creationDate": { "utc": "2025-08-01T14:22:05Z", "tz": "America/New_York" },
"lastModified": { "utc": "2025-08-02T09:11:40Z", "tz": "America/New_York" },
"subitems": []
}
],
"sections": [
{
"key": "ahNzfmdxdWV...",
"sectionId": "sec-1",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "In Progress",
"color": "gq-queue-bkgnd-8",
"notes": "",
"position": "00000000",
"isBeingDeleted": false,
"items": ["ahNzfmdxdWV1ZXMtaHJk..."]
},
{
"key": "",
"name": "(No Section)",
"color": "gq-queue-bkgnd-1",
"notes": "",
"position": "",
"items": []
}
],
"topLevelCount": 12,
"nextCursor": "50",
"limit": 50
}
Response Fields
Field | Type | Description |
| array | The page of top-level task objects (see Task Object Fields below). |
| array | The queue's sections (see Section Object Fields below). Each section's |
| integer | Total number of top-level tasks in the queue (before pagination). |
| string or null | Cursor to pass as |
| integer | The effective limit used after validation. |
Task Object Fields
This is the canonical task shape returned by List Tasks and Search Tasks. (Create Task and Update Task return a slightly smaller subset -- see those endpoints.)
Field | Type | Description |
| string | The task's datastore key. |
| string | The task title (HTML when the task is rich-text enabled). |
| string | The task notes; empty string when none. |
| boolean | Whether the task is archived. |
| boolean | Whether the task is crossed off (strikethrough, still active). |
| array | The task's tags, sorted case-insensitively. |
| string | The task's raw ordering position within its container; empty string when unset. |
| string | Name of the task's queue. |
| string | Datastore key of the task's queue. |
| integer | Number of comments on the task. |
| boolean | Whether the task has sub-tasks. |
| array | The task's attachments. Empty array if none. |
| string | The requester's access level for this task. |
| boolean | Whether the requester may add comments on this task. |
| array | Assignees (see Assignment Object Fields below); empty when unassigned. |
| string | Deep link that opens the task in the GQueues web app. Note the host is |
| string | Datastore key of the task's section. Present only on a top-level task that is in a section (and that has no task ancestry — see |
| string | Datastore key of the parent task. Present only on nested sub-tasks returned inline within a parent's |
| array | Ancestry breadcrumb for a sub-task surfaced at the top level rather than inline — as happens with |
| object | Human-readable due-date display bundle (see Due Date Object Fields below). Present only when the task has a due date. |
| object | Round-trippable schedule (see Schedule Object Fields below). Present only when the task has a due date. Pass this shape back to Update Task. |
| object | Snooze details (see Snooze Info Object Fields below). Present only when the task is snoozed. |
| object |
|
| object |
|
| object |
|
| array | Nested sub-tasks, same shape as a task object; empty array when none. |
Datetime values: creationDate, lastModified, completionDate, and snoozeInfo.until are {utc, tz} objects -- utc is an unambiguous Z-suffixed ISO-8601 instant; tz is the account's IANA timezone id. schedule.dueDate is a {local, tz} object -- local is the offset-less wall-clock string (date-only when the task has no time-of-day).
Assignment Object Fields
Field | Type | Description |
| string | The assignment's datastore key. |
| string | Assignee's email address. |
| string | Assignee's profile name. |
| string | Assignee's profile picture URL; may be empty. |
| string | Assignment comment. |
| boolean | Whether the assignee has completed the assignment. |
| boolean | Whether the requester may comment on this assignment. |
| object or null |
|
Due Date Object Fields
Field | Type | Description |
| string | Long human-readable date, e.g. |
| string | The due date as |
| integer or null | Event duration in minutes, or |
| string | Long human-readable date, with time appended when the task has a due time. |
| string | Short human-readable date (year shown only when not the current year), with time when applicable. |
| string or false | The recurrence summary string when the task repeats, otherwise |
| object |
|
Schedule Object Fields
Field | Type | Description |
| object |
|
| boolean | Whether the task has a specific time of day. |
| object |
|
| integer | Duration in minutes. Present only when set. |
| object | Recurrence rule ( |
Snooze Info Object Fields
Field | Type | Description |
| object |
|
| string or null | Unsnooze comment, or |
Section Object Fields
Field | Type | Description |
| string | Section datastore key. Empty string ( |
| string | Stable section identifier used internally (distinct from |
| string | Datastore key of the queue the section belongs to. Omitted on the "(No Section)" bucket. |
| string | Section name, as plain text. |
| string | CSS class for section color (e.g. |
| string or null | Section notes, as plain text. |
| string | Sort position key. |
| boolean |
|
| array | Task keys belonging to this section that appear on the current page. |
The "(No Section)" bucket: Every active-list response includes one synthetic section, with key: "" and name: "(No Section)", that collects the queue's top-level tasks not assigned to any named section. It carries only key, name, color, notes, position, and items — sectionId, queueKey, and isBeingDeleted are omitted. Sort sections by position to place it correctly relative to the named sections.
Pagination
To iterate through all tasks in a queue:
Make an initial request (optionally with a
limit).Read
nextCursorfrom the response.If
nextCursoris notnull, make another request withcursorset to that value.Repeat until
nextCursorisnull.
❗️Please Note: Pagination applies to top-level tasks only. Subtasks are always returned inline within their parent's subitems array.
Search Tasks
Searches tasks across all of the account's queues via full-text search. Results use the same task shape as List Tasks (each task carries its own queueName/queueKey), so they round-trip into Update Task.
GET /api/v0?action=searchTasks
Query Parameters
Parameter | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | The search query. Supports query-string syntax plus date macros such as |
| string | No | Which task states to include. Comma-separated; allowed tokens: |
| integer | No | Maximum results per page, between 1 and 25. When omitted, the server uses its default (25). |
| string | No | Opaque pagination cursor returned in a prior response's |
Request Headers
Header | Required | Description |
| Yes |
|
Example Request
curl -X GET "https://www.gqueues.com/api/v0?action=searchTasks&query=report&filter=active,archived&limit=25" \
-H "Authorization: Bearer gq_your_access_token_here"
Response
{
"items": [
{
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"title": "Draft the quarterly report",
"notes": "",
"completed": false,
"crossed": false,
"tags": ["q3"],
"position": "00000000_0001",
"queueName": "Work",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"numComments": 0,
"hasSubitems": false,
"attachments": [],
"access": "user",
"addComments": true,
"assignments": [],
"link": "https://app.gqueues.com/main/task/active/5629499534213120-6207617754725632",
"subitems": []
}
],
"nextCursor": "25_PARTITION_1.7_PARTITION_ahNzfmdxdWV1ZXMtaHJk...",
"limit": 25
}
Response Fields
Field | Type | Description |
| array | Matching task objects. Same shape as the List Tasks Task Object. Each item carries its own |
| string or null | Opaque cursor to pass as |
| integer | The effective limit used for this page. |
Please Note: Search returns 503 when search is temporarily unavailable for the account, and 403 when search is not available for the account.
Create Task
Creates one or more tasks in the authenticated user's account.
Each instruction can be submitted in one of two modes:
Structured mode (default): You supply
text(the subject), and optionally any of the structured fields below (queueKey,notes,dueDate,tags,assignments, etc.). No quick-add parsing is performed, buttextandnotesaccept basic HTML formatting (bold, italics, links, lists), which is sanitized before it is stored.Quick-add mode: Set
parseQuickAddSyntax: trueto have the server extract due date, tags, queue, assignments, and notes out of thetextusing quick-add syntax. In this mode the structured fields (queueKey,notes,dueDate, etc.) are ignored because those values are derived fromtext.
POST /api/v0
Request Headers
Header | Required | Description |
| Yes |
|
| Yes | Must be |
| Yes | Unique key for duplicate prevention. See Idempotency. |
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| array | Yes | Array of instruction objects (see below). Must be a non-empty list with at most 25 entries. The entire request body must not exceed 64 KB. |
Instruction Object
Field | Type | Required | Description |
| string | Yes | Task subject. Maximum 1,500 characters. Accepts basic HTML formatting, which is sanitized on save. In quick-add mode, this string also encodes due date, tags, queue, assignments, and notes. |
| boolean | No | If |
| string | No | Datastore key of the target queue. Obtain from Get Queues. Maximum 500 characters. If omitted, the task is added to the account's Inbox. |
| string | No | Notes body. Maximum 1,500 characters. Accepts basic HTML formatting, which is sanitized on save. |
| string | No | Due date in |
| string | No | Time of day in |
| string | No | Reminder channel: |
| integer | No | Minutes before due to send the reminder (max 40320). Requires |
| integer | No | Event duration in minutes (positive; max 527040 — one year). |
| array | No | List of tag strings (each max 1,500 bytes). |
| array | No | List of assignee email strings (max 50; each max 254 chars). |
| string | No | Datastore key of a section within the target queue. Mutually exclusive with |
| string | No | Datastore key of a parent task (creates a sub-task). Mutually exclusive with |
| string | No | Key of the task to position this new task after. Omit to place first. |
Example Request -- structured mode
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-task-a1b2c3d4" \
-d '{
"action": "createTask",
"instructions": [
{
"text": "Review API docs",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"notes": "Check the new instruction fields",
"dueDate": "2025-08-15",
"tags": ["documentation"]
}
]
}'
Example Request -- quick-add mode
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-task-e5f6g7h8" \
-d '{
"action": "createTask",
"instructions": [
{ "text": "Review API docs tomorrow #documentation [Product] :: Check the new fields", "parseQuickAddSyntax": true },
{ "text": "Send weekly report Friday at 5pm", "parseQuickAddSyntax": true }
]
}'
Response
Returns a results array with one entry per instruction, in the same order as the input.
{
"results": [
{
"status": "created",
"task": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"title": "Review API docs",
"notes": "Check the new instruction fields",
"completed": false,
"crossed": false,
"link": "https://app.gqueues.com/main/task/active/5629499534213120-4785074604081152",
"tags": ["documentation"],
"assignments": [],
"queueName": "Product",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"position": "00000000_0001",
"creationDate": { "utc": "2025-08-01T14:22:05Z", "tz": "America/New_York" },
"dueDate": {
"dueDate": "Fri, August 15",
"duration": null,
"rawDate": "2025-08-15",
"title": "Fri, August 15",
"text": "Aug 15",
"repeats": false
},
"schedule": {
"dueDate": { "local": "2025-08-15T00:00:00", "tz": "America/New_York" },
"dueTime": false
}
}
}
]
}
Result Object Fields
Field | Type | Description |
| string |
|
| object | The created task (see below). Present only on success. |
| string | Error message. Present only on failure. |
Created Task Object
The created task uses the same field conventions as the List Tasks Task Object, with these differences: it is serialized directly (so it omits the numComments, hasSubitems, attachments, access, addComments, and subitems fields that List Tasks adds), and it always includes queueName/queueKey. Present fields: key, title, notes, completed, crossed, link, tags, assignments, queueName, queueKey, position, and -- when applicable -- sectionKey, parentKey, creationDate, lastModified, completionDate, dueDate, schedule, and snoozeInfo. See the List Tasks Task Object for each field's meaning.
Request-Level Errors
These apply to the overall request and cause the entire call to fail with a 400 before any instruction is processed:
Idempotency-Key header is required-- header is missing.Idempotency-Key header must not be empty-- header is present but blank.Idempotency-Key exceeds maximum length of 128-- header exceeds the 128-character limit.Idempotency-Key contains invalid characters (allowed: a-z, A-Z, 0-9, _, -, .)-- header has disallowed characters.Instructions must be a list--instructionsis not a JSON array.Instructions list must not be empty--instructionsis an empty array.Too many instructions (max 25)--instructionsexceeds 25 entries.
Per-Instruction Error Handling
Each instruction is processed independently. If one instruction fails, the others still succeed. Possible per-instruction errors include: missing/empty text, text over 1,500 characters, invalid queueKey/sectionKey/parentKey, invalid date/reminder/duration values, an unresolvable or unauthorized queue, or an internal error.
Update Task
Updates one or more existing tasks. Each instruction targets a task by taskKey and applies exactly one editable facet (properties, tags, assignments, schedule, move, status, or snooze). To change more than one facet on a task, send it as separate instructions.
POST /api/v0
Request Headers
Same as Create Task -- requires Authorization, Content-Type: application/json, and an Idempotency-Key header.
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| array | Yes | 1 to 25 instruction objects (see below). Must be non-empty. |
Instruction Object
Each instruction must include taskKey and exactly one of the facet fields below.
Field | Type | Required | Description |
| string | Yes | Datastore key of the task to update. |
| string | -- | New task title. Non-empty (a title cannot be cleared); max 1,500 characters. May be combined with |
| string | -- | New task notes; max 1,500 characters. Combined with |
| array | -- | Full desired tag set (replace-semantics). |
| array | -- | Full desired set of assignee emails (replace-semantics). Max 50; each max 254 chars. |
| object or null | -- | Full desired date state (replace-semantics). See Schedule facet below. Send |
| object | -- | Re-position the task within its current queue. See Move facet below. |
| string | -- | One of |
| object or null | -- | Snooze the task. See Snooze facet below. Send |
Clearing a facet: schedule and snooze are the only facets whose presence counts even when the value is null -- send JSON null to clear them. For the other facets, a null value is treated as "field not supplied."
Schedule facet -- object with:
Field | Type | Required | Description |
| object | Yes |
|
| boolean | No | Whether |
| object | No |
|
| integer | No | Duration in minutes (positive; max 527040 — one year). |
| object | No |
|
Move facet -- object with:
Field | Type | Required | Description |
| string | Yes | One of |
| string | -- | Target section key. Required when |
| string | -- | Target parent task key. Required when |
| string | No | Key of the task to position this task after within the destination. Omit to place first. |
Note: Moves stay within the task's current queue; there is no cross-queue move. The task must be active or crossed (not archived, snoozed, or trashed) to be moved.
Snooze facet -- object with:
Field | Type | Required | Description |
| object | Yes |
|
| string | No | Optional unsnooze comment. |
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: update-task-a1b2c3d4" \
-d '{
"action": "updateTask",
"instructions": [
{ "taskKey": "ahNzfmdxdWV1ZXMtaHJk...", "title": "Draft the Q3 report" },
{ "taskKey": "ahNzfmdxdWV1ZXMtaHJk...", "schedule": { "dueDate": { "local": "2025-08-15T09:00:00" }, "dueTime": true } },
{ "taskKey": "ahNzfmdxdWV1ZXMtaHJk...", "snooze": null }
]
}'
Response
Returns a results array with one entry per instruction, in the same order as the input.
{
"results": [
{
"status": "updated",
"task": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"title": "Draft the Q3 report",
"notes": "",
"completed": false,
"crossed": false,
"link": "https://app.gqueues.com/main/task/active/5629499534213120-6207617754725632",
"tags": [],
"assignments": [],
"queueName": "Work",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"position": "00000000_0001"
}
},
{
"status": "error",
"error": "Not authorized to update this task"
}
]
}
Result Object Fields
Field | Type | Description |
| string |
|
| object | The updated task. Present only on success. Same serialized shape as the Create Task Created Task Object (a subset of the List Tasks Task Object). |
| string | Error message. Present only on failure. |
Please Note: Envelope-level problems (missing/empty instructions, a non-list instructions, or more than 25 instructions) fail the whole request with a 400 and no results array. Per-instruction failures (validation, not-found, not-authorized) are reported individually within results.
Delete Task
Moves one or more tasks to the trash. Deletion is recoverable -- tasks are trashed for 30 days before being permanently removed.
POST /api/v0
Request Headers
Same as Create Task -- requires Authorization, Content-Type: application/json, and an Idempotency-Key header.
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| array | Yes | 1 to 25 instruction objects (see below). Must be non-empty. |
Instruction Object
Field | Type | Required | Description |
| string | Yes | Datastore key of the task to trash. |
| boolean | No | For a recurring task: |
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: delete-task-a1b2c3d4" \
-d '{
"action": "deleteTask",
"instructions": [
{ "taskKey": "ahNzfmdxdWV1ZXMtaHJk..." },
{ "taskKey": "ahNzfmdxdWV1ZXMtaHJk...", "instanceOnly": true }
]
}'
Response
{
"results": [
{ "status": "deleted", "taskKey": "ahNzfmdxdWV1ZXMtaHJk..." },
{ "status": "error", "error": "Not authorized to delete this task" }
]
}
Result Object Fields
Field | Type | Description |
| string |
|
| string | Key of the trashed task. Present only on success. |
| string | Error message. Present only on failure. |
Please Note: As with Update Task, envelope-level problems (missing/empty/oversized instructions) fail the whole request with a 400; per-instruction failures are reported individually within results.
Create Section
Creates a new section at the end of a queue.
POST /api/v0
Request Headers
Same as Create Task -- requires Authorization, Content-Type: application/json, and an Idempotency-Key header.
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Datastore key of the queue to add the section to. Maximum 500 characters. |
| string | Yes | Section name, as plain text. Must be non-blank, and at most 250 characters once stored. |
| string | No | Optional section notes, as plain text, at most 1000 characters once stored. |
Please Note: Length is counted on the stored form, which HTML-escaping lengthens. A line break inside either value is stored as a space, and leading and trailing whitespace is trimmed -- so a value read back may be a normalized form of what was sent. See Update Section for the same rules.
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-section-a1b2c3d4" \
-d '{
"action": "createSection",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "This Week",
"notes": "Time-sensitive items"
}'
Response
{
"section": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"sectionId": "sec-1a2b3c",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "This Week",
"color": "gq-queue-bkgnd-8",
"notes": "Time-sensitive items",
"position": "00000000",
"isBeingDeleted": false
}
}
Section Object Fields
Field | Type | Description |
| string | The section's datastore key. |
| string | The section's stable client-side identifier. |
| string | Datastore key of the queue the section belongs to. |
| string | The section name. |
| string | The section color (CSS class). |
| string or null | The section notes. |
| string | The section's ordering position within the queue. |
| boolean | Whether the section is currently being deleted. |
Please Note: Validation errors return 400 (e.g. missing/empty queueKey or name, or non-string notes). When the queue does not exist or the account is not authorized to create sections in it, the response is 403 with a masked error message (the same message for not-found and not-authorized, so callers cannot probe which keys exist).
Create Queue
Creates a new personal or team queue. Exactly one of categoryKey (personal queue) or teamKey (team queue) must be supplied -- there is no default container.
POST /api/v0
Request Headers
Same as Create Task -- requires Authorization, Content-Type: application/json, and an Idempotency-Key header.
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Queue name. Non-empty; trimmed. Maximum 50 characters. |
| string | No | Optional queue notes. Maximum 1,500 characters. |
| string | Conditional | Target personal category key (from Get Categories). Supply exactly one of |
| string | Conditional | Target team key (from Get Teams). Supply exactly one of |
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-queue-a1b2c3d4" \
-d '{
"action": "createQueue",
"name": "Roadmap",
"notes": "Q3 planning",
"categoryKey": "ahNzfmdxdWV1ZXMtaHJk..."
}'
Response
Returns a queue object with the same fields as the Get Queues Queue Object.
{
"queue": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Roadmap",
"notes": "Q3 planning",
"numOpen": 0,
"numCompleted": 0,
"isInbox": false,
"dateCreated": "2025-08-01T14:22:05",
"lastModified": "2025-08-01T14:22:05",
"permission": { "view": true, "update": true, "manage": true, "publish": true },
"categoryName": "Work",
"categoryKey": "ahNzfmdxdWV1ZXMtaHJk..."
}
}
For a team queue, the response includes isTeamInbox, teamName, and teamKey instead of the category fields, and permission reflects the account's team role.
Please Note: notes is plain text in both directions -- send it as you want it read, and it comes back the same way. A line break in name is stored as a space. Use Update Queue to change any of these afterwards.
Please Note: Validation errors return 400 -- e.g. a missing/empty or too-long name, non-string or too-long notes, or supplying neither or both of categoryKey/teamKey ("Exactly one of categoryKey or teamKey is required"). When the target category or team does not exist, is deleted, or the account is not authorized to create a queue in it, the response is 403 with a single masked error message (so callers cannot probe which keys exist).
Update Queue
Renames a queue, edits its notes, or changes its color. Any combination of the three may be sent in one request; at least one is required.
POST /api/v0
Request Headers
Header | Required | Description |
| Yes |
|
| Yes |
|
| Yes | Unique key for this request (see Idempotency). |
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Datastore key of the queue to update. Maximum 500 characters. |
| string | No | New queue name. Must be non-blank and at most 50 characters -- but both rules apply only to an actual rename, so sending back the name you read is always accepted (see the note below). Requires manage rights. |
| string | No | New notes, as plain text, at most 1500 characters. Empty string clears them. Requires update rights. |
| string | No | New color, as one of the queue color classes |
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: update-queue-a1b2c3d4" \
-d '{
"action": "updateQueue",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Client Work",
"notes": "Q3 planning"
}'
Response
Returns the updated queue object, with the same fields as the Get Queues Queue Object.
{
"queue": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "Client Work",
"notes": "Q3 planning",
"numOpen": 4,
"numCompleted": 0,
"isInbox": false,
"isPage": false,
"color": "gq-queue-bkgnd-3",
"dateCreated": "2025-08-01T14:22:05",
"lastModified": "2025-08-04T09:10:11",
"permission": { "view": true, "update": true, "manage": true, "publish": true },
"editable": { "name": true, "notes": true, "color": true, "sections": true },
"categoryName": "Work",
"categoryKey": "ahNzfmdxdWV1ZXMtaHJk..."
}
}
Per-Field Permissions
Rights are checked per field, matching the web app. A request naming several fields is refused as a whole if the account lacks the rights for any one of them, and nothing is written.
Field | Right required |
| manage |
| manage |
| update |
Read the editable object on the queue (see Queue Object Fields) to know which fields this account may change on this queue before attempting a write.
Sending a name back unchanged is not a rename. A name equal to the queue's current name -- compared after the same whitespace normalization applied on write -- writes nothing and is never refused, on any queue, for any reason. That includes the length and non-blank rules, so a queue whose stored name is longer than 50 characters (names written through other clients are not bounded) can be read and posted back without a 400. Only an actual change is validated and permission-checked.
Please Note: Some queues refuse some fields regardless of rights. The personal Inbox refuses name and notes. A page-backing queue (isPage: true) refuses name and color, because both belong to the page rather than the queue -- its notes, sections and tasks remain editable. Each refusal returns 403 with an explicit message naming the reason, not a masked "not found".
Please Note: Validation errors return 400 -- e.g. a missing or over-long queueKey, a non-string name or notes, notes over 1500 characters, a color outside the vocabulary, or naming none of name/notes/color. When the queue does not exist or the account is not authorized to view it, the response is 403 with a masked error message.
Update Section
Renames a section, edits its notes, or changes its color. Any combination of the three may be sent in one request; at least one is required.
POST /api/v0
Request Headers
Header | Required | Description |
| Yes |
|
| Yes |
|
| Yes | Unique key for this request (see Idempotency). |
Request Body
Field | Type | Required | Description |
| string | Yes | Must be |
| string | Yes | Datastore key of the section to update. Maximum 500 characters. The queue is derived from the section, so no |
| string | No | New section name, as plain text. Must be non-blank, and at most 250 characters once stored (see the note on length below). |
| string | No | New section notes, as plain text, at most 1000 characters once stored. Empty string clears them. |
| string | No | New color, as one of the queue color classes |
Editing a section requires update rights on its queue -- the same right needed to add one. Read editable.sections on the queue (see Queue Object Fields) to know whether this account may edit sections there.
Example Request
curl -X POST "https://www.gqueues.com/api/v0" \
-H "Authorization: Bearer gq_your_access_token_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: update-section-a1b2c3d4" \
-d '{
"action": "updateSection",
"sectionKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "This Week",
"notes": "Time-sensitive items"
}'
Response
Returns the updated section object, with the same fields as the Get Sections Section Object.
{
"section": {
"key": "ahNzfmdxdWV1ZXMtaHJk...",
"sectionId": "sec-1a2b3c",
"queueKey": "ahNzfmdxdWV1ZXMtaHJk...",
"name": "This Week",
"color": "gq-queue-bkgnd-8",
"notes": "Time-sensitive items",
"position": "00000000",
"isBeingDeleted": false,
"collapsedByDefault": false
}
}Length is counted on the stored form. Section names and notes are stored HTML-escaped, and escaping lengthens the value -- & becomes &, and a URL in notes is stored wrapped in an anchor tag. A value that is comfortably under the limit as you send it can exceed it once stored, so a rejection message says which limit was passed and that it counts the stored form.
Please Note: A line break inside a name or notes is stored as a space; both are single-line values. Leading and trailing whitespace is trimmed. So a value read back may be a normalized form of what was sent, and posting that value back is then a no-op.
Please Note: A section that is being deleted (isBeingDeleted: true) cannot be updated and returns 403 with an explicit message. Validation errors return 400 -- e.g. a missing or over-long sectionKey, a blank name, a value past its length limit, a color outside the vocabulary, or naming none of name/notes/color. When the section does not exist, or its queue does not exist or is not viewable by the account, the response is 403 with a masked error message.