curl --request POST \
--url https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data @- <<EOF
{
"content": "Here's the invoice — pull the totals."
}
EOFconst options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({content: 'Here\'s the invoice — pull the totals.'})
};
fetch('https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages"
payload = { "content": "Here's the invoice — pull the totals." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"status": "success",
"data": {
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"thread_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"state": "running"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}Send a message
Post a user message and start (or resume) a run. Returns 202 with a run_id. Poll the run, or subscribe to realtime, for the assistant reply. If a run is awaiting_input, this message is the answer.
curl --request POST \
--url https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data @- <<EOF
{
"content": "Here's the invoice — pull the totals."
}
EOFconst options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({content: 'Here\'s the invoice — pull the totals.'})
};
fetch('https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.usepatchwork.co/v1/loom/threads/{thread_id}/messages"
payload = { "content": "Here's the invoice — pull the totals." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"status": "success",
"data": {
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"thread_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"state": "running"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}{
"status": "error",
"error": {
"message": "<string>",
"code": "<string>",
"details": "<unknown>"
}
}Authorizations
Identify accepts a workspace API key (sk_…). Loom accepts either a short-lived session token (direct) or a workspace API key (relay).
Headers
Makes this POST safe to retry. The first call does the work and its response is stored; a retry with the same key returns that stored response with Idempotency-Replayed: true, without charging again. Same key with a different body is rejected. Keys expire after 24 hours.
255Relay only. Opaque subject id, chosen by you and never resolved by Patchwork. Partitions threads and memory within your workspace. Direct tokens carry sub instead — do not send this header on a session token.
Required on every subject-scoped resource: threads, messages, runs, outcomes, confirmations and realtime. Omitting it is subject_required, never a wider result. The value is used exactly as given — never trimmed or normalised — so a stray space creates a second partition and is refused as invalid_subject.
Connection id or name the agent may call. Required in relay when the agent has unpinned customer tools. Direct tokens may carry conn instead.