curl --request GET \
--url https://api.blujay.io/v1/phone-numbers/{phone_number_id} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blujay.io/v1/phone-numbers/{phone_number_id}', 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/{phone_number_id}"
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/{phone_number_id}"
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/{phone_number_id}")
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/{phone_number_id}",
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_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"
}{
"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>"
}Get a phone number
Returns one of your Blujay numbers with the same detail as the list. A number that has been retired returns status: unavailable and never reports current health, capacity, label or calling readiness.
curl --request GET \
--url https://api.blujay.io/v1/phone-numbers/{phone_number_id} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.blujay.io/v1/phone-numbers/{phone_number_id}', 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/{phone_number_id}"
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/{phone_number_id}"
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/{phone_number_id}")
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/{phone_number_id}",
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_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"
}{
"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>"
}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
^phone_[A-Za-z0-9_-]+$"phone_abc123"
Response
The phone number.
Wraps every successful response. The result is in data.
success ^trc_[A-Za-z0-9_-]+$"trc_8f2a1c0e4b7d"
"2026-10-14T17:01:00.000Z"
A Blujay number in your workspace and what it can do right now. Numbers on the Shared Free Plan omit health, limits, queue and calling readiness.
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.