curl --request GET \
--url https://api.pictor.cloud/api/devices \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.pictor.cloud/api/devices"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.pictor.cloud/api/devices', 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://api.pictor.cloud/api/devices",
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;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pictor.cloud/api/devices"
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))
}HttpResponse<String> response = Unirest.get("https://api.pictor.cloud/api/devices")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictor.cloud/api/devices")
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{
"items": [
{
"capabilities": [
"live",
"recording"
],
"central_account_ref": "4021",
"channel": 1,
"client_id": "2e3f4a51-6b7c-4d8e-9f01-1a2b3c4d5e6f",
"client_name": "Cond. Alvorada",
"codec": "h264",
"connection": {
"credentials_required": true,
"settings": {
"channel": 1,
"device_serial": null,
"remote_port": null
},
"type": "rtsp_direct"
},
"device_id": "EXEMPLO-0001",
"device_type": "ip_camera",
"device_uuid": "0b8f1c22-6d4e-4a17-9b02-3f5a7c8d9e10",
"dvr_id": "3a4b5c60-7d8e-4f01-a2b3-c4d5e6f70819",
"dvr_name": "DVR Portaria",
"dvr_total_channels": 16,
"image_state": "with_frame",
"last_frame_at": "2026-09-03T18:42:11Z",
"last_seen": "2026-09-03T18:42:11Z",
"live": "online",
"live_status_available": true,
"location": {
"name": "Portaria",
"zone": "Perímetro"
},
"manufacturer": "Intelbras",
"model": "VIP 1230 B",
"monitored_site_id": "1d2e3f40-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"monitored_site_name": "Cond. Alvorada - Portaria",
"name": "Guarita - entrada",
"status": "online",
"tax_id": "12.345.678/0001-90",
"thumbnail_url": "/api/thumbs/EXEMPLO-0001",
"transmitting": "yes"
}
],
"limit": 100,
"offset": 0,
"total": 128,
"transmitting_window_seconds": 900,
"transmitting_witness_fresh": true,
"transmitting_witness_last_success_at": "2026-09-03T18:41:03Z"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Listar câmeras
As câmeras que esta chave enxerga, paginadas, com o local monitorado e o cliente-dono já resolvidos em cada linha.
status é CADASTRO e transmitting é IMAGEM: para saber quem está sem imagem
agora, filtre transmitting=no. device_id é único dentro da conta, não entre
contas. Ver Casar os dois cadastros.
curl --request GET \
--url https://api.pictor.cloud/api/devices \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.pictor.cloud/api/devices"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.pictor.cloud/api/devices', 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://api.pictor.cloud/api/devices",
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;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.pictor.cloud/api/devices"
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))
}HttpResponse<String> response = Unirest.get("https://api.pictor.cloud/api/devices")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictor.cloud/api/devices")
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{
"items": [
{
"capabilities": [
"live",
"recording"
],
"central_account_ref": "4021",
"channel": 1,
"client_id": "2e3f4a51-6b7c-4d8e-9f01-1a2b3c4d5e6f",
"client_name": "Cond. Alvorada",
"codec": "h264",
"connection": {
"credentials_required": true,
"settings": {
"channel": 1,
"device_serial": null,
"remote_port": null
},
"type": "rtsp_direct"
},
"device_id": "EXEMPLO-0001",
"device_type": "ip_camera",
"device_uuid": "0b8f1c22-6d4e-4a17-9b02-3f5a7c8d9e10",
"dvr_id": "3a4b5c60-7d8e-4f01-a2b3-c4d5e6f70819",
"dvr_name": "DVR Portaria",
"dvr_total_channels": 16,
"image_state": "with_frame",
"last_frame_at": "2026-09-03T18:42:11Z",
"last_seen": "2026-09-03T18:42:11Z",
"live": "online",
"live_status_available": true,
"location": {
"name": "Portaria",
"zone": "Perímetro"
},
"manufacturer": "Intelbras",
"model": "VIP 1230 B",
"monitored_site_id": "1d2e3f40-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"monitored_site_name": "Cond. Alvorada - Portaria",
"name": "Guarita - entrada",
"status": "online",
"tax_id": "12.345.678/0001-90",
"thumbnail_url": "/api/thumbs/EXEMPLO-0001",
"transmitting": "yes"
}
],
"limit": 100,
"offset": 0,
"total": 128,
"transmitting_window_seconds": 900,
"transmitting_witness_fresh": true,
"transmitting_witness_last_success_at": "2026-09-03T18:41:03Z"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Authorizations
Chave de API da conta, no formato pct_<prefixo>_<segredo>.
Query Parameters
Quantas câmeras por página. Máximo 500.
1 <= x <= 500Por onde começar a página. Use com limit para paginar.
x >= 0Busca por nome da câmera, identificador do equipamento, rótulo do local, gravador, local monitorado ou cliente. Busca por nome da câmera, external_id, rótulo do local, DVR, nome do Local Monitorado ou do cliente-dono, ou pelo código da conta do local (igual ou começando por)
Recorte por situação de cadastro: online ou offline. Para saber quem está sem imagem, use transmitting.
Filtro server-side: online | offline
Recorte por IMAGEM, independente de status. yes = chegou imagem dentro da janela; no = já chegou antes desta câmera, e não dentro da janela; unknown = nunca chegou imagem desta câmera.
Eixo de IMAGEM (testemunha de quadro), independente de status: yes = chegou quadro dentro da janela; no = já chegou quadro, mas fora da janela; unknown = nunca chegou quadro desta câmera
^(yes|no|unknown)$Só as câmeras deste cliente. Recorte exato por cliente-dono (UUID)
Só as câmeras deste local monitorado. Recorte exato por Local Monitorado (UUID)
Só as câmeras deste gravador (UUID)
Só as câmeras destes identificadores de equipamento, separados por vírgula. Máximo de 16. Hidratação por external_id (CSV, máx 16) — a rota do mural, que exibe no máximo 16 câmeras
Só o que mudou desde este instante (ISO 8601, com fuso). Devolve também removed, as câmeras APAGADAS na janela — sem elas o delta faria o seu cadastro guardar câmera que não existe mais.
Inclui o resumo de causa sobre o recorte inteiro. Desligado por padrão: é uma agregação sobre todas as câmeras e custa tempo na resposta.
Inclui diagnostico_resumo (rollup de causa sobre o recorte inteiro). DESLIGADO por padrão: é uma agregação sobre todas as câmeras do recorte, e no maior tenant custa ~30 ms — caro demais para a abertura normal da grade, que não desenha o resumo.
imagem (padrão) põe primeiro quem está entregando imagem, depois por recência da última. recentes usa a ordem de cadastro. Com a medição de imagem parada, imagem cai para recentes.
imagem (default) = câmeras que estão entregando quadro primeiro, depois por recência do último quadro; recentes = ordem de cadastro (comportamento anterior). Com a testemunha de quadro parada, imagem cai para recentes. Para varrer o tenant inteiro por limit+offset (reconciliação, export), use recentes: imagem ordena por uma coluna que muda a todo instante, e isso pula ou repete device entre páginas.
^(imagem|recentes)$Response
Successful Response