Tickets
`/tickets`
One page of records, newest first unless you say otherwise, with the total count in meta so you know how far to paginate.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
page?integer1-based. meta.totalPages says how many there are.
1 <= value1per_page?integerRows per page. A value above 200 returns 400 - never a silent clamp.
1 <= value <= 20050sort?stringPrefix with - for descending. An undeclared sort returns 400.
"-createdAt""createdAt""-createdAt""dueDate""-dueDate""priority""-priority""status""-status""resolvedAt""-resolvedAt"q?stringCase-insensitive "contains", across: title, description.
filter[status]?stringExact match on status.
filter[priority]?stringExact match on priority.
"low""medium""high""urgent"filter[difficulty]?stringExact match on difficulty.
filter[scope]?stringExact match on scope.
"client""agency""internal"filter[clientVisible]?stringExact match on clientVisible.
"true""false"filter[clientId]?stringExact match on clientId.
filter[projectId]?stringExact match on projectId.
filter[parentId]?stringExact match on parentId.
filter[assigneeId]?stringExact match on assigneeId.
filter[categoryId]?stringExact match on categoryId.
filter[teamId]?stringExact match on teamId.
filter[milestoneId]?stringExact match on milestoneId.
filter[cycleId]?stringExact match on cycleId.
filter[open]?stringtrue for tickets not yet in a terminal column of the agency's workflow, false for the finished ones. Reads the agency's own columns, never the literal done.
"true""false"filter[archived]?stringfalse (the default) leaves archived tickets out; true lists only them. Put away with bulk-update { archived: true }.
"true""false"filter[withinProjectId]?stringA project's public id: the tickets of that project AND of its sub-projects. filter[projectId] reads one project (or one sub-project) only.
The requested page.
application/json- response
data*array<>meta*curl -X GET 'https://api.usedashly.com/v1/tickets'{ "data": [ { "id": "string", "title": "string", "description": "string", "scope": "client", "status": "string", "priority": "low", "clientVisible": true, "dueDate": "2019-08-24T14:15:22Z", "estimateMinutes": 0, "difficulty": "string", "commitRef": "string", "resolvedAt": "2019-08-24T14:15:22Z", "resolvedById": "string", "archivedAt": "2019-08-24T14:15:22Z", "clientId": "string", "projectId": "string", "parentId": "string", "assigneeId": "string", "categoryId": "string", "teamId": "string", "milestoneId": "string", "cycleId": "string", "createdAt": "2019-08-24T14:15:22Z", "customFields": {} } ], "meta": { "page": 0, "perPage": 0, "total": 0, "totalPages": 0 }}Links are given as the target's public id (clientId: "hsbftmp3f5"); the API resolves them server-side. Fields the database requires but the interface decides for you are filled in the same way here.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
title*string1 <= length <= 300description?string|nullscope?stringclient or agency. internal is a deprecated alias of agency, stored as agency.
"client""agency""internal"status?string1 <= length <= 40priority?string"low""medium""high""urgent"clientVisible?booleandueDate?string|nullestimateMinutes?|nulldifficulty?|nullcommitRef?|nullclientId?string|nullprojectId?string|nullparentId?string|nullassigneeId?string|nullcategoryId?string|nullcustomFields?milestoneId?string|nullcycleId?string|nullcreatedAt?stringWhen this actually happened, for an import. Past dates only; defaults to now. updatedAt follows it unless the body sets one.
date-timeCreated. The body is the new record, as a read would return it.
application/json- response
data*curl -X POST 'https://api.usedashly.com/v1/tickets' \ -H 'Content-Type: application/json' \ -d '{ "title": "string"}'{ "data": { "id": "string", "title": "string", "description": "string", "scope": "client", "status": "string", "priority": "low", "clientVisible": true, "dueDate": "2019-08-24T14:15:22Z", "estimateMinutes": 0, "difficulty": "string", "commitRef": "string", "resolvedAt": "2019-08-24T14:15:22Z", "resolvedById": "string", "archivedAt": "2019-08-24T14:15:22Z", "clientId": "string", "projectId": "string", "parentId": "string", "assigneeId": "string", "categoryId": "string", "teamId": "string", "milestoneId": "string", "cycleId": "string", "createdAt": "2019-08-24T14:15:22Z", "customFields": {} }}The full record, custom fields included when the resource carries them. A record from another agency is a 404, not a 403 - its existence is not ours to confirm.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe record's public id (hsbftmp3f5), as returned in the id field. An internal UUID returns 404.
Found.
application/json- response
data*curl -X GET 'https://api.usedashly.com/v1/tickets/string'{ "data": { "id": "string", "title": "string", "description": "string", "scope": "client", "status": "string", "priority": "low", "clientVisible": true, "dueDate": "2019-08-24T14:15:22Z", "estimateMinutes": 0, "difficulty": "string", "commitRef": "string", "resolvedAt": "2019-08-24T14:15:22Z", "resolvedById": "string", "archivedAt": "2019-08-24T14:15:22Z", "clientId": "string", "projectId": "string", "parentId": "string", "assigneeId": "string", "categoryId": "string", "teamId": "string", "milestoneId": "string", "cycleId": "string", "createdAt": "2019-08-24T14:15:22Z", "customFields": {} }}A partial update: only the fields you send change. One exception - customFields is replaced wholesale, not merged, so sending it with a single key clears the others. Read the record, merge, then write.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe record's public id (hsbftmp3f5), as returned in the id field. An internal UUID returns 404.
application/json- body
title?string1 <= length <= 300description?string|nullscope?stringclient or agency. internal is a deprecated alias of agency, stored as agency.
"client""agency""internal"status?string1 <= length <= 40priority?string"low""medium""high""urgent"clientVisible?booleandueDate?string|nullestimateMinutes?|nulldifficulty?|nullcommitRef?|nullclientId?string|nullprojectId?string|nullparentId?string|nullassigneeId?string|nullcategoryId?string|nullcustomFields?milestoneId?string|nullcycleId?string|nullUpdated. The body is the record as it now stands.
application/json- response
data*curl -X PATCH 'https://api.usedashly.com/v1/tickets/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "data": { "id": "string", "title": "string", "description": "string", "scope": "client", "status": "string", "priority": "low", "clientVisible": true, "dueDate": "2019-08-24T14:15:22Z", "estimateMinutes": 0, "difficulty": "string", "commitRef": "string", "resolvedAt": "2019-08-24T14:15:22Z", "resolvedById": "string", "archivedAt": "2019-08-24T14:15:22Z", "clientId": "string", "projectId": "string", "parentId": "string", "assigneeId": "string", "categoryId": "string", "teamId": "string", "milestoneId": "string", "cycleId": "string", "createdAt": "2019-08-24T14:15:22Z", "customFields": {} }}Permanent. The audit log keeps the trace; the record does not come back.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe record's public id (hsbftmp3f5), as returned in the id field. An internal UUID returns 404.
Deleted. Empty body.
curl -X DELETE 'https://api.usedashly.com/v1/tickets/string'Every verb this resource answers to, with its target and the JSON Schema of its body - the same contracts this document describes, readable at runtime.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
The available verbs.
application/json- response
data*array<>curl -X GET 'https://api.usedashly.com/v1/tickets/actions'{ "data": [ { "name": "string", "label": "string", "description": "string", "target": "item", "readOnly": true, "path": "string", "input": {} } ]}Declares that this ticket is blocked by another one (dependsOnId). Refuses self-blocking and an immediate reverse dependency.
Does what the dashboard's addTicketDependencyAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
dependsOnId*string1 <= lengthDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/add-dependency' \ -H 'Content-Type: application/json' \ -d '{ "dependsOnId": "string"}'{ "data": null}Removes the "blocked by" link between this ticket and the ticket named by dependsOnId.
Does what the dashboard's removeTicketDependencyAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
dependsOnId*string1 <= lengthDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/remove-dependency' \ -H 'Content-Type: application/json' \ -d '{ "dependsOnId": "string"}'{ "data": null}Adds an attachment to this ticket: base64 content, 5 MB maximum once decoded, stored in the private bucket and visible in the dashboard straight away.
Does what the dashboard's uploadAttachmentAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
fileName*string1 <= length <= 200contentType?stringlength <= 120data*string^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$base64length <= 6990508Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/upload-attachment' \ -H 'Content-Type: application/json' \ -d '{ "fileName": "string", "data": "string"}'{ "data": null}Deletes this ticket's attachment with the given filename, row and stored file alike. Refused when two of the ticket's attachments share that name.
Does what the dashboard's deleteAttachmentAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
fileName*string1 <= length <= 200Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/delete-attachment' \ -H 'Content-Type: application/json' \ -d '{ "fileName": "string"}'{ "data": null}For a ticket filed from the review widget: each remark behind it with its page (URL, title, release), the reviewer's environment (browser and version, OS, device, viewport, language, raw user-agent), the zone pointed at (selector, text, coordinates), the page's errors and a screenshot URL valid 10 minutes. remarks is empty for a ticket that did not come from the widget.
Reads the same data as the in-app listWidgetFeedbackForTicket - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
The figures.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X GET 'https://api.usedashly.com/v1/tickets/string/actions/widget-context'{ "data": null}For a ticket filed from the review widget: each remark behind it with its page (URL, title, release), the reviewer's environment (browser and version, OS, device, viewport, language, raw user-agent), the zone pointed at (selector, text, coordinates), the page's errors and a screenshot URL valid 10 minutes. remarks is empty for a ticket that did not come from the widget.
Reads the same data as the in-app listWidgetFeedbackForTicket - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/widget-context' \ -H 'Content-Type: application/json' \ -d '{}'{ "data": null}Creates a relation between this record and a target object (targetType plus the target's public targetId) in the relation graph. Linking the same pair twice does nothing.
Does what the dashboard's linkObjectAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
targetType*string"account""contact""project""ticket""deal""user""proposal"targetId*string1 <= length <= 60Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/link-object' \ -H 'Content-Type: application/json' \ -d '{ "targetType": "account", "targetId": "string"}'{ "data": null}Removes the relation between this record and the target object in the relation graph. Unlinking a pair that was never linked does nothing. A deal/project pair is unlinked like unlink-project on the deal: the change is audited, so the key must be attached to a user (403 with reason key_not_attached otherwise).
Does what the dashboard's unlinkObjectAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
targetType*string"account""contact""project""ticket""deal""user""proposal"targetId*string1 <= length <= 60Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/unlink-object' \ -H 'Content-Type: application/json' \ -d '{ "targetType": "account", "targetId": "string"}'{ "data": null}Merges the listed tickets (sourceIds, public ids) into this one, in one transaction: this ticket keeps its title, their descriptions are appended under a heading each, and their comments, attachments, subtasks, assignees (added after this ticket's own), links, dependencies, time, relations and history move here; each source is archived with a comment and a relation pointing here. A source of another client needs confirmClientChange: true; a source this ticket is a subtask of is refused; dryRun: true answers the counts without writing. Re-running the same merge changes nothing (alreadyMerged).
Does what the dashboard's mergeTicketsAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
sourceIds*array<>1 <= items <= 50confirmClientChange?booleandryRun?booleanDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/merge' \ -H 'Content-Type: application/json' \ -d '{ "sourceIds": [ "string" ]}'{ "data": null}Replaces the ticket's assignees with assigneeIds (member ids from /v1/members), in order; the first becomes the ticket's assigneeId. An empty list unassigns it. At most 10.
Does what the dashboard's setTicketAssigneesAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
assigneeIds*array<>items <= 10Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/set-assignees' \ -H 'Content-Type: application/json' \ -d '{ "assigneeIds": [ "string" ]}'{ "data": null}On at most 200 tickets at once, in one write: add puts the member after the people already there, remove takes them off (the next person becomes the ticket's assigneeId), replace makes them the only assignee — or unassigns every ticket with assigneeId: null. Agency members only.
Does what the dashboard's bulkEditTicketAssigneesAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
itemIds*array<>1 <= items <= 200mode*string"add""remove""replace"assigneeId*|nullDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/actions/bulk-assignees' \ -H 'Content-Type: application/json' \ -d '{ "itemIds": [ "string" ], "mode": "add", "assigneeId": "string"}'{ "data": null}Everyone the ticket is assigned to, in order: assigneeIds (member ids from /v1/members) and each person's name. The first is the ticket's assigneeId.
Reads the same data as the in-app listTicketAssignees - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
The figures.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X GET 'https://api.usedashly.com/v1/tickets/string/actions/assignees'{ "data": null}Everyone the ticket is assigned to, in order: assigneeIds (member ids from /v1/members) and each person's name. The first is the ticket's assigneeId.
Reads the same data as the in-app listTicketAssignees - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/assignees' \ -H 'Content-Type: application/json' \ -d '{}'{ "data": null}Replaces the ticket's client-side assignees: memberIds (members of the ticket's client portal, from the client-assignees read's candidates), in order, and/or clientSide: true for the client organisation as a whole. A member of another client is refused (not_a_client_member). Assigning makes the ticket visible in the client's portal: pass makeClientVisible: true when it is not yet. The newly assigned are notified (portal bell; email for a signed client). Not counted as agency workload.
Does what the dashboard's setTicketClientAssigneesAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
memberIds*array<>items <= 10clientSide?booleanfalsemakeClientVisible?booleanfalseDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/set-client-assignees' \ -H 'Content-Type: application/json' \ -d '{ "memberIds": [ "string" ]}'{ "data": null}Who on the client's side the ticket is assigned to — clientSide (the organisation) and members — and candidates, every member of the ticket's client portal it may be assigned to. clientId is null for a ticket without client.
Reads the same data as the in-app listTicketClientAssignees - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
The figures.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X GET 'https://api.usedashly.com/v1/tickets/string/actions/client-assignees'{ "data": null}Who on the client's side the ticket is assigned to — clientSide (the organisation) and members — and candidates, every member of the ticket's client portal it may be assigned to. clientId is null for a ticket without client.
Reads the same data as the in-app listTicketClientAssignees - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/client-assignees' \ -H 'Content-Type: application/json' \ -d '{}'{ "data": null}The Sentry issues the ticket names, each read live from the agency's Sentry (title, project, status, event and user counts, first and last seen, link). When Sentry is not connected or cannot answer, an issue comes back with issue: null, its href when one is known, and error (not_connected, other_org, unauthorized, not_found, upstream...).
Reads the same data as the in-app readTicketSentryIssues - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
The figures.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X GET 'https://api.usedashly.com/v1/tickets/string/actions/sentry-issues'{ "data": null}The Sentry issues the ticket names, each read live from the agency's Sentry (title, project, status, event and user counts, first and last seen, link). When Sentry is not connected or cannot answer, an issue comes back with issue: null, its href when one is known, and error (not_connected, other_org, unauthorized, not_found, upstream...).
Reads the same data as the in-app readTicketSentryIssues - same implementation. Changes nothing; also answers GET with the same fields as query parameters.
Required scope: tickets:read.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/sentry-issues' \ -H 'Content-Type: application/json' \ -d '{}'{ "data": null}Adds Sentry issues after the ticket's own: issue URLs (sentry.io, us.sentry.io, de.sentry.io), short ids (WEB-1) or numeric ids. One value that is none of these refuses the whole call (sentry_issue_invalid, details.invalid). When the ticket is resolved, its issues are resolved in Sentry.
Does what the dashboard's addTicketSentryIssuesAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
issues*array<>1 <= items <= 10Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/add-sentry-issues' \ -H 'Content-Type: application/json' \ -d '{ "issues": [ "string" ]}'{ "data": null}Removes one issue by the key the read returns (WEB-1, 4512345678). An unknown key changes nothing. The issue itself is untouched in Sentry.
Does what the dashboard's removeTicketSentryIssueAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
key*string1 <= length <= 100Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/remove-sentry-issue' \ -H 'Content-Type: application/json' \ -d '{ "key": "string"}'{ "data": null}Replaces the ticket's Sentry issues with issues, in that order; [] clears them. Same values and refusals as add-sentry-issues.
Does what the dashboard's setTicketSentryIssues does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
issues*array<>items <= 10Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/set-sentry-issues' \ -H 'Content-Type: application/json' \ -d '{ "issues": [ "string" ]}'{ "data": null}Applies the same change - status, priority, difficulty, category, assignee, archived - to at most 200 tickets in a single write. The status is checked against the agency's workflow columns.
Does what the dashboard's bulkUpdateWorkItemsAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
itemIds*array<>1 <= items <= 200status?string1 <= length <= 40priority?string"low""medium""high""urgent"difficulty?|nullarchived?booleancategoryId?|nullassigneeId?|nullDone.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/actions/bulk-update' \ -H 'Content-Type: application/json' \ -d '{ "itemIds": [ "string" ]}'{ "data": null}Replaces the ticket's body (a BlockNote document) and rewrites its plain-text description at the same time - the one the portal, the e-mails and search read.
Does what the dashboard's setTicketContentAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
id*stringThe public id of the record to act on. It is resolved inside your agency before the action runs, so an id from another tenant is a 404 and never reaches it.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
content*array<unknown>items <= 2000Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/string/actions/set-content' \ -H 'Content-Type: application/json' \ -d '{ "content": [ null ]}'{ "data": null}Replaces the agency's workflow columns wholesale - between 2 and 12, at least one terminal and one non-terminal. Tickets left in a deleted column move to the first non-terminal column, and the response says how many.
Does what the dashboard's saveWorkflowAction does - same implementation, so the two cannot diverge.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255application/json- body
columns*array<>2 <= items <= 12Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/actions/save-workflow' \ -H 'Content-Type: application/json' \ -d '{ "columns": [ { "label": "string", "color": "slate", "isDone": true }, { "label": "string", "color": "slate", "isDone": true } ]}'{ "data": null}Restores the five columns the product ships with, moving tickets left in a deleted column to the first non-terminal one.
Does what the dashboard's resetWorkflowAction does - same implementation, so the two cannot diverge. Takes no body.
Required scope: tickets:write.
bearerAuthAuthorizationBearer <token>Your agency's API key: Authorization: Bearer ak_…. Created in Connectors → API & webhooks and shown once. A key authenticates an agency, not a person.
Idempotency-Key?stringA value you choose (a UUID is the usual one), 8 to 255 characters of A-Z a-z 0-9 _ . : -. Retrying with the same key returns the first call's answer instead of creating a second record, for seven days. The same key with a different body returns 409.
8 <= length <= 255Done.
application/json- response
data*unknownThe action's result; its shape depends on the verb.
curl -X POST 'https://api.usedashly.com/v1/tickets/actions/reset-workflow'{ "data": null}