curl --request PATCH \
--url https://api.blujay.io/v1/chats/{chat_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"display_name": "Project kickoff"
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({display_name: 'Project kickoff'})
};
fetch('https://api.blujay.io/v1/chats/{chat_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.blujay.io/v1/chats/{chat_id}"
payload = { "display_name": "Project kickoff" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.blujay.io/v1/chats/{chat_id}"
payload := strings.NewReader("{\n \"display_name\": \"Project kickoff\"\n}")
req, _ := http.NewRequest("PATCH", 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))
}require 'uri'
require 'net/http'
url = URI("https://api.blujay.io/v1/chats/{chat_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"display_name\": \"Project kickoff\"\n}"
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.blujay.io/v1/chats/{chat_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'display_name' => 'Project kickoff'
]),
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;
}{
"status": "success",
"data": {
"chat_id": "chat_abc123",
"operation": "group_name_update",
"status": "accepted",
"display_name": "Project kickoff"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T21:00:00.000Z"
}{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "<string>",
"type": "validation",
"http_status": 400,
"retryable": true,
"doc_url": "<string>",
"details": [
{}
],
"retry_after": 2,
"reset_at": "2026-10-14T17:01:00.000Z"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"client_request_id": "<string>"
}{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "<string>",
"type": "validation",
"http_status": 400,
"retryable": true,
"doc_url": "<string>",
"details": [
{}
],
"retry_after": 2,
"reset_at": "2026-10-14T17:01:00.000Z"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"client_request_id": "<string>"
}{
"status": "error",
"error": {
"code": "PHONE_NUMBER_UNAVAILABLE",
"message": "This service is temporarily unavailable",
"type": "phone_number",
"http_status": 503,
"retryable": true,
"doc_url": "https://docs.blujay.io/errors/phone-number-unavailable",
"details": [],
"retry_after": 30
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T00:00:00.000Z"
}Rename a group chat
Sets the name of an active iMessage group chat. Everyone in the group sees the new name. Blujay returns 202 once the change is accepted.
You can’t clear a group name, and the group icon can’t be changed through the API yet. If the chat isn’t an active iMessage group, you get 400 UNSUPPORTED_CHAT_OPERATION.
curl --request PATCH \
--url https://api.blujay.io/v1/chats/{chat_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"display_name": "Project kickoff"
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({display_name: 'Project kickoff'})
};
fetch('https://api.blujay.io/v1/chats/{chat_id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.blujay.io/v1/chats/{chat_id}"
payload = { "display_name": "Project kickoff" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.blujay.io/v1/chats/{chat_id}"
payload := strings.NewReader("{\n \"display_name\": \"Project kickoff\"\n}")
req, _ := http.NewRequest("PATCH", 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))
}require 'uri'
require 'net/http'
url = URI("https://api.blujay.io/v1/chats/{chat_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"display_name\": \"Project kickoff\"\n}"
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.blujay.io/v1/chats/{chat_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'display_name' => 'Project kickoff'
]),
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;
}{
"status": "success",
"data": {
"chat_id": "chat_abc123",
"operation": "group_name_update",
"status": "accepted",
"display_name": "Project kickoff"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T21:00:00.000Z"
}{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "<string>",
"type": "validation",
"http_status": 400,
"retryable": true,
"doc_url": "<string>",
"details": [
{}
],
"retry_after": 2,
"reset_at": "2026-10-14T17:01:00.000Z"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"client_request_id": "<string>"
}{
"status": "error",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "<string>",
"type": "validation",
"http_status": 400,
"retryable": true,
"doc_url": "<string>",
"details": [
{}
],
"retry_after": 2,
"reset_at": "2026-10-14T17:01:00.000Z"
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:01:00.000Z",
"client_request_id": "<string>"
}{
"status": "error",
"error": {
"code": "PHONE_NUMBER_UNAVAILABLE",
"message": "This service is temporarily unavailable",
"type": "phone_number",
"http_status": 503,
"retryable": true,
"doc_url": "https://docs.blujay.io/errors/phone-number-unavailable",
"details": [],
"retry_after": 30
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T00:00:00.000Z"
}Authorizations
Your workspace API key, sent as Authorization: Bearer blu_.... Workspace admins can find it in the Blujay app under API.
An API key has full access to your workspace and works on every endpoint. There is no test mode: every key sends real messages and changes real data, so keep it secret and use it only from your server.
Each API key can make 600 read requests and 120 write requests per minute, plus 60 attachment requests per minute. Over a limit you get 429 RATE_LIMIT_EXCEEDED with Retry-After.
Path Parameters
^chat_[A-Za-z0-9_-]+$"chat_abc123"
Body
Changes to a group chat. Only display_name is supported, for active iMessage group chats.
The new group name. It can't be empty; you can't clear a group name through the API.
1 - 100"Order 4821 support"
Response
The rename was accepted.
Wraps every successful response. The result is in data.
success ^trc_[A-Za-z0-9_-]+$"trc_8f2a1c0e4b7d"
"2026-10-14T17:01:00.000Z"
Show child attributes
Show child attributes
Your X-Request-ID header value, echoed back when you send one. Not included on the send responses (POST /v1/chats, POST /v1/chats/{chat_id}/messages, POST /v1/messages/{message_id}/retry); keep your own mapping from your request ID to the returned message ID there.