curl --request GET \
--url https://api.blujay.io/v1/phone-numbers \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blujay.io/v1/phone-numbers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.blujay.io/v1/phone-numbers"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.blujay.io/v1/phone-numbers"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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/phone-numbers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.blujay.io/v1/phone-numbers",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"status": "success",
"data": {
"phone_numbers": [
{
"phone_number_id": "phone_abc123",
"display_number": "+15555550100",
"label": "Sales",
"status": "active",
"line_type": "outbound",
"access_type": "dedicated",
"send_status": {
"allowed": true
},
"health_status": {
"status": "healthy",
"score": 98,
"as_of": "2026-10-14T17:00:00.000Z",
"freshness": "fresh"
},
"limits": {
"new_contacts": {
"used_today": 12,
"limit_per_day": 50,
"remaining_today": 38,
"reset_at": "2026-10-15T07:00:00.000Z"
},
"daily": {
"used_today": 140,
"guideline": 250,
"remaining_to_guideline": 110,
"enforced": false
}
},
"queue": {
"pending": 3,
"capacity": 1500,
"remaining": 1497
},
"capabilities": {
"messaging": {
"outbound": true,
"inbound": true,
"media_attachments": true,
"link_parts": true
},
"voice": {
"outbound_ready": true,
"inbound_forwarding_ready": true
}
},
"outbound_policy": {
"inbound_first": false,
"first_message_links_allowed": false,
"follow_up_links_allowed": true,
"daily_total_enforced": false
}
}
]
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17:00:00.000Z"
}List phone numbers
Returns the Blujay numbers in your workspace. For each number you get whether it can send right now (send_status), what it supports (capabilities), and its link rules (outbound_policy).
Dedicated numbers also report health_status, queue, and limits. Sending limits and queue capacity, such as how many new contacts a number can message per day, are specific to each number and change over time. Read the live values from limits and queue instead of hard-coding them.
curl --request GET \
--url https://api.blujay.io/v1/phone-numbers \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blujay.io/v1/phone-numbers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.blujay.io/v1/phone-numbers"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.blujay.io/v1/phone-numbers"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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/phone-numbers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.blujay.io/v1/phone-numbers",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}{
"status": "success",
"data": {
"phone_numbers": [
{
"phone_number_id": "phone_abc123",
"display_number": "+15555550100",
"label": "Sales",
"status": "active",
"line_type": "outbound",
"access_type": "dedicated",
"send_status": {
"allowed": true
},
"health_status": {
"status": "healthy",
"score": 98,
"as_of": "2026-10-14T17:00:00.000Z",
"freshness": "fresh"
},
"limits": {
"new_contacts": {
"used_today": 12,
"limit_per_day": 50,
"remaining_today": 38,
"reset_at": "2026-10-15T07:00:00.000Z"
},
"daily": {
"used_today": 140,
"guideline": 250,
"remaining_to_guideline": 110,
"enforced": false
}
},
"queue": {
"pending": 3,
"capacity": 1500,
"remaining": 1497
},
"capabilities": {
"messaging": {
"outbound": true,
"inbound": true,
"media_attachments": true,
"link_parts": true
},
"voice": {
"outbound_ready": true,
"inbound_forwarding_ready": true
}
},
"outbound_policy": {
"inbound_first": false,
"first_message_links_allowed": false,
"follow_up_links_allowed": true,
"daily_total_enforced": false
}
}
]
},
"trace_id": "trc_8f2a1c0e4b7d",
"timestamp": "2026-10-14T17: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.
Response
Your active phone numbers, oldest first. Retired numbers are left out; read one with GET /v1/phone-numbers/{phone_number_id}.
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.