Working with tasks and tickets
Tasks represent planned work. Tickets represent inbound requests and reactive work. The public API lets integrations read and update both while preserving the permissions and state rules used by AgencyTitan.
Start with the API Quickstart for authentication, envelopes, pagination, errors, and rate limits. The examples below assume:
BASE_URL="https://api.agencytitan.com"List and filter tasks
Section titled “List and filter tasks”GET /v1/tasks returns task-grain rows. Several row fields, including status, assigned_to, due_date, priority_level, and start_date, describe the current stage.
Use first-class query parameters for common filters:
curl "$BASE_URL/v1/tasks?status_scope=active&client_ids=66666666-6666-4666-8666-666666666666&sort=due_date&order=asc&limit=50" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Accept: application/json"Useful filters include:
status_scope,statuses,assigned_to,due_date_from, anddue_date_tofor the current stageprocess_status_scope,process_statuses,process_assigned_to, andprocess_due_date_fromfor the parent taskclient_ids,process_definition_id,priority_level, andtagsfor task-level selectionfilter_groupfor supported custom-field and nested conditions
Values within one array filter are combined with OR. Different filters are combined with AND. Resolve status, priority, and tag values with GET /v1/tasks/options instead of guessing tenant-configured values.
For assigned work at stage grain, use GET /v1/task-stages and filter by assigned_to.
Update current-stage status, assignment, or due date
Section titled “Update current-stage status, assignment, or due date”POST /v1/tasks/manage is an action-enum composite for three same-risk updates. The required action selects one of:
update_status, withstatusassign, with anassigned_toarray that replaces the current-stage assignmentset_due_date, with an ISO 8601due_dateornullto clear it
For example:
curl --request POST "$BASE_URL/v1/tasks/manage" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "action": "set_due_date", "task_id": "11111111-1111-4111-8111-111111111111", "due_date": "2026-08-15T17:00:00Z" }'Use the status values returned by GET /v1/tasks/options for update_status.
Update custom task fields
Section titled “Update custom task fields”POST /v1/tasks/update-fields patches custom fields by registered field key:
curl --request POST "$BASE_URL/v1/tasks/update-fields" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "task_id": "11111111-1111-4111-8111-111111111111", "field_values": { "campaign_url": "https://example.com/campaign", "estimated_hours": 8 } }'The operation rejects system task fields. Use the dedicated task or stage operation for status, assignment, and dates. Valid custom fields are attempted independently, and the response reports each field as applied or rejected; inspect every result instead of treating HTTP 200 as proof that every field changed.
Move a task to another stage
Section titled “Move a task to another stage”POST /v1/tasks/transition-stage moves a task only along a declared transition from its current stage:
curl --request POST "$BASE_URL/v1/tasks/transition-stage" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "task_id": "11111111-1111-4111-8111-111111111111", "target_stage_id": "22222222-2222-4222-8222-222222222222", "reason": "Client approved the deliverable" }'An undeclared target, unmet dependency, or missing required field returns a conflict without changing the task. The optional reason is invocation context returned to the caller; it is not stored on the task.
Create and update tickets
Section titled “Create and update tickets”GET /v1/tickets supports search, resource-specific sorting, and filters for status, client, assignee, department, inbox, priority, tags, SLA state, and creation time.
Create a ticket with POST /v1/tickets. subject is required; description, client_id, assigned_to, and priority are optional.
Use PATCH /v1/tickets/{id} to replace provided fields only. It can change status, priority, client link, and the full assignee set. An empty assigned_to array or null clears assignment.
The composite POST /v1/tickets/manage can create or update a ticket and can add a safe internal note to an existing ticket. Its comment field never queues an outbound reply.
Assign tickets
Section titled “Assign tickets”POST /v1/tickets/{id}/assign supports two actions:
manualreplaces the full assignee set. An empty array unassigns the ticket. You can also providetarget_inbox_idto move and assign atomically andreasonfor audit context.smartruns AgencyTitan’s live assignment scorer. Do not send manual-assignment fields with this action.
curl --request POST "$BASE_URL/v1/tickets/99999999-9999-4999-8999-999999999999/assign" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "action": "manual", "assigned_to": ["33333333-3333-4333-8333-333333333333"], "reason": "Route to the web support team" }'Read ticket conversations
Section titled “Read ticket conversations”GET /v1/ticket-messages requires ticket_id and returns inbound and outbound messages plus internal notes. The default order is chronological. Use is_internal_note as the stable discriminator.
curl "$BASE_URL/v1/ticket-messages?ticket_id=99999999-9999-4999-8999-999999999999&order=asc" \ --header "Authorization: Bearer $AGENCYTITAN_API_KEY" \ --header "Accept: application/json"Attachment references are metadata only. Follow Files and attachments to obtain a download URL.
GET /v1/ticket-messages/{id} also requires the parent ticket_id query parameter because conversation-item reads are ticket-scoped.
Operations rolling out
Section titled “Operations rolling out”These capabilities are not yet fully exposed by the current OpenAPI document:
- Task creation. The existing
tasks.manageoperation intentionally omits creation. Live task creation can apply billing and deferred-creation rules and can optionally advance a stage, so the planned operation is approval-gated instead of being treated as a simple insert. - Outbound ticket sending. Conversation reads, internal notes, and reply drafts are available now:
POST /v1/ticket-drafts/savecreates or updates a draft, and theticket-draftstag includes read and review-queue operations. A saved draft always keepsdraftdelivery status; the operation that actually sends an outbound message is still rolling out. - Linking tasks to tickets. Ticket and task records can be managed independently, but no public link or unlink operation is in the current reference.
Do not guess route names or request bodies for rolling-out operations. Wait until an operation appears in the generated API reference and the current OpenAPI document before calling it.