Updating Issues
Write changes back to SpeakUp from a system your team already works in. You can change an Issue's status, reassign it, move it between domains, apply labels, and set custom field values.
Two methods do this. PATCH updates only the fields you send. PUT replaces the Issue and requires every field defined for its type. Both return the complete updated Issue, and both are recorded in the Issue history.
The API does not create Issues. Issues enter SpeakUp through your reporting Channels.
To read Issue data, see Retrieving Issues.
On this page: Request format · Permissions · Issue types · Choosing PUT or PATCH · PATCH · PUT · Response · Field rules · Custom field values · What happens after an update · Errors
Request format
Send all request bodies with Content-Type: application/json.
When a value contains line breaks or other special characters, encode it properly for JSON, using \n for new lines.
Both methods take the Issue ID as a path parameter.
| Parameter | Required | Description |
|---|---|---|
id |
Yes | The unique identifier of the Issue to update. |
Permissions
Requires an App Integration with full access for Issues. Read only access cannot update. See how do I create an App Integration and get API credentials?
Issue types
Issue types fall into two groups. The group determines which fields apply, and which are required when updating.
Standard Issues
Standard Issues support the full set of properties. This covers Case and any custom Issue type created in your system.
Standard Issues support domain, labels, and issueFields in addition to the core fields.
Sub Issues
Sub Issues support a limited set of fields. The only Sub Issue type is Task.
Sub Issues do not support domain, labels, or issueFields. Sending any of them returns an error. A PUT on a Sub Issue requires only the core fields.
An Issue's type is returned when you retrieve it. See Retrieving Issues. Check the type before building a request.
Choosing PUT or PATCH
| Aspect | PATCH | PUT |
|---|---|---|
| Behaviour | Updates only the fields you send. Everything else is unchanged. | Replaces the Issue. |
| Required fields | None. All body fields are optional. | All fields required for the Issue type. |
| Custom fields | Send only the fields you want to change. | Every issueFieldId for the Issue type must be present. |
| Use it when | You are changing one or two values. | Your system holds the complete Issue state. |
PATCH is usually the right choice. With PUT, changing a single value means retrieving the Issue first and resending the existing values for every other field, and omitting one causes the request to fail.
Both methods reject an empty request body with a 400.
PATCH: update selected fields
PATCH /v1/public/issues/{id}
Updates only the fields included in the request body. All other fields remain unchanged. Every body field is optional, but the body cannot be empty. Fields not supported by the Issue type are rejected.
Examples
Update the summary only:
curl -X PATCH '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{ "summary": "Updated security incident summary" }'
Update several fields at once:
curl -X PATCH '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"summary": "Updated summary",
"status": "In Progress",
"assigneeId": 45,
"dueDate": "2025-12-25"
}'
Update custom field values:
curl -X PATCH '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"issueFields": [
{ "issueFieldId": 101, "value": "Critical" },
{ "issueFieldId": 102, "value": "Database Server, Web Application" }
]
}'
Unassign an Issue:
curl -X PATCH '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{ "assigneeId": null }'
Remove all labels:
curl -X PATCH '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{ "labels": [] }'
PUT: replace an Issue
PUT /v1/public/issues/{id}
Replaces the Issue with a complete update. All required fields for the Issue type must be included. Missing required fields return a 400, and the response names what is missing.
Required fields
| Field | Type | Standard Issue | Sub Issue |
|---|---|---|---|
summary |
String | Required | Required |
description |
String | Required | Required |
status |
String | Required | Required |
dueDate |
String | Required | Required |
assigneeId |
Number or null | Required | Required |
domain |
String | Required | Not supported |
labels |
Array of strings | Required | Not supported |
issueFields |
Array | Required | Not supported |
For a standard Issue, every custom field defined for the Issue type must be present in issueFields. Omitting one returns a 400 naming the missing IDs.
Examples
Replace a standard Issue:
curl -X PUT '{API_BASE_URL}/v1/public/issues/1001' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"summary": "Security incident involving unauthorized access",
"description": "A comprehensive security incident report.",
"status": "In Progress",
"domain": "IT Security",
"labels": ["Security", "High Priority"],
"dueDate": "2025-12-25",
"assigneeId": 45,
"issueFields": [
{ "issueFieldId": 101, "value": "High" },
{ "issueFieldId": 102, "value": "Database Server, Web Application" }
]
}'
Replace a Sub Issue. Sub Issues take the core fields only, so domain, labels, and issueFields are omitted:
curl -X PUT '{API_BASE_URL}/v1/public/issues/1002' \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"summary": "Follow up with the IT team",
"description": "Confirm access controls have been applied.",
"status": "In Progress",
"dueDate": "2025-12-25",
"assigneeId": 45
}'
Response
Both methods return the complete updated Issue, in the same shape as the get endpoint. See Retrieving Issues for the full field reference.
{
"id": 1001,
"summary": "Updated summary",
"description": "Updated description",
"type": "Case",
"status": "In Progress",
"resolution": null,
"assignee": "John Doe",
"assigneeId": 45,
"domain": "IT Security",
"labels": ["Security", "High Priority"],
"customId": "SEC-2024-001",
"dueDate": "2025-12-25T00:00:00.000Z",
"parentId": null,
"acknowledgedAt": "2024-12-01T09:15:30.123Z",
"receivedAt": "2024-12-01T09:10:15.456Z",
"closedAt": null,
"createdAt": "2024-12-01T09:10:15.456Z",
"updatedAt": "2024-12-18T10:30:00.000Z",
"issueFields": [ ... ],
"issueForms": [ ... ],
"reportForms": [ ... ],
"reportDetails": { ... }
}
Field rules
summary
The Issue summary. Maximum 500 characters.
"summary": "Employee reported inappropriate workplace behavior"
description
The Issue description. Maximum 50,000 characters.
"description": "Inappropriate comments were made during a team meeting."
status
The status to set on the Issue. Must match one of the statuses defined in the workflow for the current Issue type. Cannot be null.
If the new status belongs to the Done category, the Issue's closedAt timestamp is set automatically.
"status": "New"
dueDate
The due date for the Issue, in ISO 8601 format. Two formats are accepted. If only a date is given, the time defaults to 00:00:00 UTC.
"dueDate": "2026-01-28"
"dueDate": "2026-01-28T14:30:00"
assigneeId
The ID of the User to assign the Issue to. The User must exist, be enabled, not be a service or support user, and have access to the Issue.
"assigneeId": 10
Set to null to unassign the Issue.
"assigneeId": null
domain
The domain the Issue belongs to. Must match a domain in your system, and that domain must not be archived. Cannot be null. Standard Issues only.
Changing the domain sends email notifications to Users with access to it.
"domain": "IT"
labels
The labels applied to the Issue, as an array of label names. Label names are case sensitive, and each must be between 1 and 250 characters. Standard Issues only.
"labels": ["IT", "Security"]
Send an empty array or null to remove all labels.
"labels": []
issueFields
Custom field values, as an array of objects. Each object contains an issueFieldId and a value. Standard Issues only.
Every issueFieldId must exist for the current Issue type. Valid IDs and their field types come from the Issue itself, so retrieve it first. See Retrieving Issues.
With PUT, every field defined for the Issue type must be included. With PATCH, include only the fields you want to change.
"issueFields": [
{ "issueFieldId": 1, "value": "Incident reported" },
{ "issueFieldId": 7, "value": "2026-01-28T14:30:00" }
]
Set a value to null to clear the field.
Custom field values
All issueFields values are sent as strings, whatever the underlying field type.
Short text
Maximum 128 characters.
"issueFields": [
{ "issueFieldId": 1, "value": "Incident reported" }
]
Number
A valid integer, sent as a string.
"issueFields": [
{ "issueFieldId": 2, "value": "2" }
]
Boolean
Sent as the string "true" or "false".
"issueFields": [
{ "issueFieldId": 3, "value": "true" }
]
Option list
The value must be one of the allowed options for that field.
"issueFields": [
{ "issueFieldId": 4, "value": "Netherlands" }
]
Multiple option list
Each selected option is sent as a separate object, all using the same issueFieldId. Values must come from the allowed options.
"issueFields": [
{ "issueFieldId": 5, "value": "Netherlands" },
{ "issueFieldId": 5, "value": "India" }
]
Date
ISO 8601 date, formatted YYYY-MM-DD.
"issueFields": [
{ "issueFieldId": 6, "value": "2026-01-28" }
]
Date time
ISO 8601 date and time, formatted YYYY-MM-DDTHH:mm:ss.
"issueFields": [
{ "issueFieldId": 7, "value": "2026-01-28T14:30:00" }
]
What happens after an update
Issue history
Every change is recorded in the Issue history and attributed to your App Integration by name.
App integration MyApp updated the summary
App integration MyApp updated the status from New to In Progress
App integration MyApp updated the assignee from Unassigned to John Doe
See Retrieving Issue activity to retrieve the log.
Notifications
- Changing the assignee sends an email notification to the new assignee.
- Changing the domain sends email notifications to Users with access to that domain.
Webhooks
For standard Issues, webhooks are triggered when any of these properties are updated: summary, description, status, domain, assignee, due date, labels, and Issue fields.
See How do I configure webhooks?
Errors
See the API error reference for the full list, including response format. These are the conditions specific to updating.
400 Bad Request
| Condition | What to do |
|---|---|
| The request body is missing. | Both methods require a body. |
| The body is empty, malformed, or contains unrecognised fields. | Check the field names against the field rules above. |
| A PUT request is missing required fields. | The response names the missing fields. Retrieve the Issue first and resend its current values, or use PATCH instead. |
| A PUT request is missing required custom fields. | The response names the missing issueFieldId values. PUT requires every custom field defined for the Issue type. |
| The body contains fields the Issue type does not support. | Sub Issues reject domain, labels, and issueFields. Check the Issue's type first. |
| The assignee has no access to the Issue. | Choose a User with access to the Issue's domain. |
| The domain is archived. | Archived domains cannot be set on an Issue. Choose an active domain. |
403 Forbidden
| Condition | What to do |
|---|---|
| The integration has read only access. | Updating requires full access for Issues. See how do I create an App Integration and get API credentials? |
| The Public API package is not enabled. | Contact your Customer Success Manager. |
404 Not Found
Returned when a value in the request refers to something that does not exist. The response names which one.
| Condition | What to do |
|---|---|
| The Issue does not exist, or the integration cannot access it. | Check the ID against the list endpoint. |
The assigneeId does not exist. |
The User must exist, be enabled, and not be a service or support user. |
The status does not exist. |
Statuses come from the workflow for the Issue type. |
The domain does not exist. |
Domain names are matched exactly. |
One or more issueFieldId values do not exist for the Issue type. |
Retrieve the Issue to get its valid field IDs. See Retrieving Issues. |