Upload a record collaboration attachment
Collaboration is feature-gated and scoped to accessible task, donor, recipient, sponsorship or space_page records in the organization. Archived subjects are read-only409; Support Sessions cannot write. Editing comments requires authorship; pinning requires management access. Revisions and request UUIDs protect concurrent edits. Downloads require a safe scan and existing stored bytes.
curl --request POST \
--url https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--header 'Idempotency-Key: <idempotency-key>' \
--form file=@example-file \
--form comment_id=1 \
--form draft_context_id=b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605import requests
url = "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"comment_id": "1",
"draft_context_id": "b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>"
}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('comment_id', '1');
form.append('draft_context_id', 'b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605');
const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', Authorization: 'Bearer <token>'}
};
options.body = form;
fetch('https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"data": {
"id": 123,
"name": "<string>",
"mime": "<string>",
"size": 123,
"status": "<string>",
"comment_id": 123,
"created_at": "2023-11-07T05:31:56Z",
"permissions": {
"delete": true
}
}
}{
"message": "Unauthorized",
"status": "error"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Not Found",
"status": "error"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}Authorizations
Passport bearer token authentication for legacy admin sessions.
Headers
UUID for this upload request. Reuse only for the identical file and draft/subject context.
Path Parameters
Supported collaboration subject type.
ID of the accessible collaboration subject.
Body
Request fields accepted by this operation. Omitted optional properties retain the behavior described above.
Required file, at most 10240KB. PDF, JPEG/PNG/GIF/WebP, plain text/CSV, Word and Excel formats are accepted; extension must match detected MIME.
Optional comment association; mutually exclusive with draft_context_id.
1
Optional unsaved comment draft UUID; mutually exclusive with comment_id.
"b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605"
Response
Upload a record collaboration attachment response.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--header 'Idempotency-Key: <idempotency-key>' \
--form file=@example-file \
--form comment_id=1 \
--form draft_context_id=b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605import requests
url = "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"comment_id": "1",
"draft_context_id": "b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>"
}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
form.append('comment_id', '1');
form.append('draft_context_id', 'b2e01bb7-6c5a-4bc6-9ee6-20b5a4295605');
const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', Authorization: 'Bearer <token>'}
};
options.body = form;
fetch('https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gratona.com/v1/admin/collaboration/{subjectType}/{subjectId}/attachments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"comment_id\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"draft_context_id\"\r\n\r\nb2e01bb7-6c5a-4bc6-9ee6-20b5a4295605\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"data": {
"id": 123,
"name": "<string>",
"mime": "<string>",
"size": 123,
"status": "<string>",
"comment_id": 123,
"created_at": "2023-11-07T05:31:56Z",
"permissions": {
"delete": true
}
}
}{
"message": "Unauthorized",
"status": "error"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"message": "Not Found",
"status": "error"
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}{
"errors": {},
"status": "error",
"message": "The given data was invalid."
}{
"message": "Something went wrong. Please try again.",
"status": "error",
"error": "invalid_request",
"code": "DONOR_NOT_FOUND"
}