Upload a file and attach it to an existing comment.
The method validates the current user’s permission to edit the target comment, checks file and storage limits, creates an attachment record, and schedules the uploaded file for transfer to permanent storage.
Task, track, and project associations are inherited from the target comment. They cannot be selected independently in this request.
The number in the URL path (/1/) is the organization identifier — referred to as account_id.
This value must match the account associated with the provided session_id or token.
Use POST with multipart/form-data.
The uploaded file must be provided in the file form field. A GET request cannot perform a successful upload because it cannot include the required file payload.
curl -X POST "https://api.doboard.com/42/attachment_add" \
-F "session_id=abc123xyz" \
-F "comment_id=501" \
-F "file=@screenshot.png" \
-F "filename=login-error.png" \
-F "attachment_order=0"
In this example:
42 is the organization/account ID.session_id=abc123xyz is used for authentication.comment_id=501 identifies the comment receiving the attachment.file contains the uploaded file.filename defines the attachment’s display filename.attachment_order=0 defines its numeric order value.
comment_idandfileare required.
Required
The method requires a valid session or guest/public access context:
session_id – for authenticated userstoken – for guest/public accessAccess is also determined by the ownership and editing state of the target comment.
The comment owner can add attachments unless another user is actively editing the comment.
An editing session is considered active for 15 minutes from its last recorded editing time.
A user who does not own the comment can add an attachment only when all of the following conditions are met:
A guest who owns the comment can upload attachments, subject to the guest upload limits.
A guest cannot upload an attachment to a comment owned by another user.
A non-owner cannot upload an attachment to a track-only comment because the first-comment editing exception applies only to comments associated with tasks.
If the account ID in the URL does not match the account tied to the session or token, the request will be rejected.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
session_id |
string | Yes* | – | Authenticated user session ID. |
token |
string | Yes* | – | Guest/public access token. |
comment_id |
int | Yes | – | ID of the existing comment that will receive the attachment. |
file |
binary file | Yes | – | File uploaded through the multipart/form-data request. The form field must be named file. |
filename |
string | No | Uploaded filename | Display filename stored for the attachment. Maximum 255 characters; longer values are truncated. |
attachment_order |
int | No | 0 |
Numeric attachment order. Allowed range: 0 to 4294967295. |
* Either session_id or token is required.
The following association fields are not accepted as independent inputs:
task_idtrack_idproject_idTheir values are copied from the selected comment.
| User context | Attachment permission |
|---|---|
| Comment owner; no other active editor | Allowed |
| Comment owner; another user has an active editing session | Denied |
| Guest who does not own the comment | Denied |
| Non-owner; track-only comment | Denied |
| Non-owner; task comment that is not the first active comment | Denied |
| Non-owner; first active task comment with a current editing session | Allowed |
| Non-owner; first active task comment edited by the same user within the last 60 seconds | Allowed |
| Non-owner; editing session has expired and no recent edit is recorded | Denied |
No separate administrator bypass is applied to these comment-editing rules.
The following limits are taken from the current server configuration:
| Limit | Authenticated user | Guest user |
|---|---|---|
| Maximum size of one file | 100 MiB (104857600 bytes) |
5 MiB (5242880 bytes) |
| Maximum size of a recognized image | 10 MiB (10485760 bytes) |
5 MiB effective guest limit |
| Maximum attachments per comment | 30 | 5 |
| Maximum cumulative attachment size per comment | 1 GiB (1073741824 bytes) |
25 MiB (26214400 bytes) |
Guest uploads are checked against both the general limits and the stricter guest limits.
For accounts with a configured storage quota, the upload is also rejected when the account has already reached that quota.
The following MIME types are treated as images:
image/pngimage/jpegimage/webpThese files:
The MIME type is detected from the uploaded file rather than taken from a request parameter.
This method does not apply a general MIME-type allowlist. Other file types can be uploaded if they pass the applicable file-size, count, storage, and access checks.
When filename is supplied:
When filename is omitted:
A custom filename changes the attachment’s stored display name. The temporary upload URL is generated from the normalized original upload filename.
{
"data": {
"operation_status": "SUCCESS",
"attachment_id": 301
}
}
attachment_id contains the ID of the newly created attachment.
The response does not include the complete attachment object or its final permanent URL.
{
"data": {
"operation_status": "FAILED",
"operation_message": "comment_id is required"
},
"error_message": "comment_id is required",
"error_no": 1003
}
Validation, access, and storage-limit errors are returned with HTTP status 200. Authentication failure uses HTTP status 401.
The method creates a new record in the attachments table.
| Field | Type | Description |
|---|---|---|
attachment_id |
int | Unique attachment identifier generated after creation. |
created |
datetime | Date and time when the attachment was created. |
updated |
datetime | Date and time when the attachment was created or last updated. |
filename |
string | Attachment display filename, up to 255 characters. |
URL |
string | File URL. Initially points to temporary upload storage and can be updated after transfer to permanent storage. |
URL_thumbnail |
string/null | Generated thumbnail URL for supported images. It can be populated asynchronously. |
comment_id |
int | ID of the comment receiving the attachment. |
user_id |
int | ID of the user who uploaded the file. |
mime_content_type |
string | MIME type detected from the uploaded file. |
attachment_order |
int | Numeric order value from 0 to 4294967295. |
task_id |
int/null | Task ID copied from the comment. |
track_id |
int/null | Track ID copied from the comment. |
project_id |
int/null | Project ID copied from the comment. |
file_size |
int | Uploaded file size in bytes. |
After the request passes validation:
attachment_id.The API can return success before the background storage and thumbnail operations have completed.
The attachment’s URL, URL_thumbnail, and related counters may therefore be updated shortly after the initial response.
After successful attachment creation, the method performs or schedules the following actions:
INSERT event with attachment data to the account WebSocket channel when realtime publishing is available.Example WebSocket event:
{
"action": "INSERT",
"object": "attachments",
"data": {
"...": "created attachment data"
}
}
The initial WebSocket event can contain the temporary file URL because permanent storage transfer and thumbnail generation occur afterward.
| HTTP Code | error_no |
Message | Description |
|---|---|---|---|
401 |
– | Unauthorized |
Missing or invalid session/token. |
200 |
1001 |
Comment not found |
The requested comment_id does not exist. |
200 |
1002 |
Access denied |
The current user does not satisfy the comment ownership or editing-state requirements. |
200 |
1003 |
comment_id is required |
comment_id was not provided or was empty. |
200 |
1004 |
file is empty |
The uploaded file has a size of zero bytes. |
200 |
1005 |
File size greater than {limit} bytes. |
The file exceeds the general or guest per-file limit. |
200 |
1006 |
file is required |
The file field is missing or does not contain a valid HTTP upload. |
200 |
1007 |
Storage limit exceeded. Upgrade your package. |
The account has reached its configured storage quota. |
200 |
1008 |
Image file size is greater than {limit} bytes. |
A PNG, JPEG, or WebP image exceeds the configured image-size limit. |
200 |
1009 |
Maximum number of attachments exceeded — up to {limit} allowed. |
The comment already contains the maximum permitted number of attachments. |
200 |
1010 |
Total attachments limit per comment — 1 GB. |
The new file would exceed the cumulative attachment-size limit for an authenticated user. |
200 |
1010 |
Total attachments limit per comment — 25 MB. |
The new file would exceed the cumulative attachment-size limit for a guest. |
200 |
1017 |
Out of range value in attachment_order |
attachment_order is below 0 or above 4294967295. |
200 |
0 |
Internal API Error |
The attachment record could not be created. |
comment_id.file multipart form field.filename is optional and is limited to 255 characters.attachment_order is 0.attachment_id.attachment_get.