curl --request POST \
--url https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"body": "Kan vi ändra startdatum till den 1 december?",
"parentMessageId": null,
"mentions": [
"cm4k2x9p10002abcd1234efgh"
]
}
'import requests
url = "https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages"
payload = {
"body": "Kan vi ändra startdatum till den 1 december?",
"parentMessageId": None,
"mentions": ["cm4k2x9p10002abcd1234efgh"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
body: JSON.stringify('Kan vi ändra startdatum till den 1 december?'),
parentMessageId: null,
mentions: ['cm4k2x9p10002abcd1234efgh']
})
};
fetch('https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages', 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://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'body' => 'Kan vi ändra startdatum till den 1 december?',
'parentMessageId' => null,
'mentions' => [
'cm4k2x9p10002abcd1234efgh'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages"
payload := strings.NewReader("{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "cm4k2x9p10019abcd1234efgh",
"threadId": "cm4k2x9p10018abcd1234efgh",
"parentId": "cm4k2x9p10019abcd1234efgh",
"body": "Kan vi ändra startdatum till den 1 december?",
"mentions": [
"cm4k2x9p10002abcd1234efgh"
],
"createdAt": "2026-09-28T09:12:00.000Z",
"editedAt": null,
"deletedAt": null,
"author": {
"type": "USER",
"id": "cm4k2x9p10002abcd1234efgh",
"name": "Alex Berg",
"email": "[email protected]"
}
}{
"code": "VALIDATION_FAILED",
"message": "Invalid input: expected string, received undefined",
"userMessage": "Förfrågan innehåller ogiltiga värden.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"issues": [
{
"path": "body",
"code": "INVALID_TYPE",
"message": "Invalid input: expected string, received undefined"
}
]
}{
"code": "UNAUTHORIZED",
"message": "Invalid API token",
"userMessage": "Ogiltig API-nyckel",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "INSUFFICIENT_SCOPE",
"message": "Insufficient OAuth scope: requires documents:write",
"userMessage": "Applikationen saknar behörighet (scope) för denna åtgärd.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"requiredScopes": [
"documents:write"
],
"grantedScopes": [
"profile:read"
]
}{
"code": "NOT_FOUND",
"message": "Message not found",
"userMessage": "Resursen hittades inte.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"resource": "message"
}{
"code": "INVALID_STATE",
"message": "The resource's current state doesn't allow the operation, such as editing a document that was already sent or downloading a file that isn't produced yet.",
"userMessage": "Åtgärden är inte möjlig i resursens nuvarande status.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "RATE_LIMITED",
"message": "API rate limit exceeded",
"userMessage": "För många förfrågningar. Försök igen om en stund.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "INTERNAL_ERROR",
"message": "Internal server error",
"userMessage": "Något gick fel.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "UPSTREAM_UNAVAILABLE",
"message": "A service the operation depends on, such as an eID provider or a connected integration, failed or is unavailable. Retry with exponential backoff.",
"userMessage": "En extern tjänst svarar inte just nu. Försök igen om en stund.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}Add a message to a comment thread
Append a reply or new message to an existing comment thread on a document. Posting to a resolved thread will reopen it.
curl --request POST \
--url https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"body": "Kan vi ändra startdatum till den 1 december?",
"parentMessageId": null,
"mentions": [
"cm4k2x9p10002abcd1234efgh"
]
}
'import requests
url = "https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages"
payload = {
"body": "Kan vi ändra startdatum till den 1 december?",
"parentMessageId": None,
"mentions": ["cm4k2x9p10002abcd1234efgh"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
body: JSON.stringify('Kan vi ändra startdatum till den 1 december?'),
parentMessageId: null,
mentions: ['cm4k2x9p10002abcd1234efgh']
})
};
fetch('https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages', 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://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'body' => 'Kan vi ändra startdatum till den 1 december?',
'parentMessageId' => null,
'mentions' => [
'cm4k2x9p10002abcd1234efgh'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages"
payload := strings.NewReader("{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sajn.se/api/v1/documents/{id}/comments/{threadId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"body\": \"Kan vi ändra startdatum till den 1 december?\",\n \"parentMessageId\": null,\n \"mentions\": [\n \"cm4k2x9p10002abcd1234efgh\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"id": "cm4k2x9p10019abcd1234efgh",
"threadId": "cm4k2x9p10018abcd1234efgh",
"parentId": "cm4k2x9p10019abcd1234efgh",
"body": "Kan vi ändra startdatum till den 1 december?",
"mentions": [
"cm4k2x9p10002abcd1234efgh"
],
"createdAt": "2026-09-28T09:12:00.000Z",
"editedAt": null,
"deletedAt": null,
"author": {
"type": "USER",
"id": "cm4k2x9p10002abcd1234efgh",
"name": "Alex Berg",
"email": "[email protected]"
}
}{
"code": "VALIDATION_FAILED",
"message": "Invalid input: expected string, received undefined",
"userMessage": "Förfrågan innehåller ogiltiga värden.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"issues": [
{
"path": "body",
"code": "INVALID_TYPE",
"message": "Invalid input: expected string, received undefined"
}
]
}{
"code": "UNAUTHORIZED",
"message": "Invalid API token",
"userMessage": "Ogiltig API-nyckel",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "INSUFFICIENT_SCOPE",
"message": "Insufficient OAuth scope: requires documents:write",
"userMessage": "Applikationen saknar behörighet (scope) för denna åtgärd.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"requiredScopes": [
"documents:write"
],
"grantedScopes": [
"profile:read"
]
}{
"code": "NOT_FOUND",
"message": "Message not found",
"userMessage": "Resursen hittades inte.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2",
"resource": "message"
}{
"code": "INVALID_STATE",
"message": "The resource's current state doesn't allow the operation, such as editing a document that was already sent or downloading a file that isn't produced yet.",
"userMessage": "Åtgärden är inte möjlig i resursens nuvarande status.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "RATE_LIMITED",
"message": "API rate limit exceeded",
"userMessage": "För många förfrågningar. Försök igen om en stund.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "INTERNAL_ERROR",
"message": "Internal server error",
"userMessage": "Något gick fel.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}{
"code": "UPSTREAM_UNAVAILABLE",
"message": "A service the operation depends on, such as an eID provider or a connected integration, failed or is unavailable. Retry with exponential backoff.",
"userMessage": "En extern tjänst svarar inte just nu. Försök igen om en stund.",
"requestId": "req_V1StGXR8Z5jdHi6BmyT2"
}Authorizations
Personal API key, e.g. Authorization: Bearer sajn_sk_.... Not scope-limited — acts as the issuing user.
Headers
API version for this request. Without it, the request uses the organization's default version; an organization without a default is pinned to the latest version by its first request.
2026-09, 2026-10 Makes retries safe. A retry with the same key and the same request replays the stored response for 24 hours (header Idempotent-Replayed: true); the same key with a different request returns 400.
255Body
Body
Response
200
The message ID.
The comment thread ID.
The ID of the message this one replies to. Null for a top-level message.
The message text.
IDs of the users the message mentions.
When the message was created.
When the message was last edited. Null if it never was.
When the message was deleted. Null if it wasn't.
Who wrote the message.
Show child attributes
Show child attributes
Was this page helpful?

