GET /contacts
Lista todos los contactos que pertenecen a la cuenta. Se puede especificar un filtro para obtener resultados más específicos.
Parámetros opcionales
| Parámetro | Tipo | Descripción |
|---|---|---|
page | Integer | La página de contactos. Si no se especifica, el valor predeterminado es la página 1. Las páginas más allá de la 500 no están disponibles — usa la paginación por cursor en su lugar. |
after | string | Cursor opaco obtenido del meta.next de una respuesta anterior. Devuelve el lote de contactos que le sigue. Ver Paginación por cursor. |
source | Source | El tipo de integración (p. ej. whatsapp) |
tags | string[] | Las etiquetas coincidentes, separadas por comas (p. ej. sales,lead). Las etiquetas no distinguen mayúsculas de minúsculas. |
team_uuid | string | El uuid del equipo. |
include_field_types | boolean | Cuando es true, la respuesta incluye customFieldsMetadata con el valor, tipo y opciones de cada campo personalizado. |
Paginación por cursor
La paginación por páginas se detiene en la página 500 (10.000 contactos): las solicitudes más allá de ese límite devuelven un error 400 Bad Request con el mensaje Pagination limit exceeded. Para recorrer la lista completa de contactos, usa la paginación por cursor:
- Haz una solicitud como de costumbre: cada respuesta incluye un token opaco en
meta.next. - Devuelve el token a través del parámetro
afterpara obtener el siguiente lote de contactos. - Sigue el valor de
meta.nexthasta que seanull: eso marca el último lote.
curl -X GET "https://api.callbell.eu/v1/contacts?after=eyJ0cyI6MTc1NDM4NDQwMDAwMCwiaWQiOjEyMzQ1fQ" \
-H "Authorization: Bearer test_gshuPaZoeEG6ovbc8M79w0QyM" \
-H "Content-Type: application/json"
Algunas cosas a tener en cuenta:
- Trata el token como opaco y devuélvelo sin modificar. Un token malformado devuelve un error
400 Bad Requestcon el mensajeInvalid pagination cursor. - El parámetro
pagese ignora cuandoafterestá presente. - Los filtros (
source,tags,team_uuid) no están codificados en el token: envía los mismos filtros junto conafteren cada solicitud. - Los contactos se devuelven en el mismo orden que en las solicitudes por páginas (la conversación más reciente primero). Los contactos creados después de iniciar el recorrido no se incluyen.
Ejemplo de solicitud
- cURL
- Node
- Ruby
- Go
- PHP
- Python
- C#
- Java
- Rust
curl -X GET "https://api.callbell.eu/v1/contacts" \
-H "Authorization: Bearer test_gshuPaZoeEG6ovbc8M79w0QyM" \
-H "Content-Type: application/json"
import axios from 'axios';
const response = await axios.get('https://api.callbell.eu/v1/contacts', {
headers: {
'Authorization': 'Bearer test_gshuPaZoeEG6ovbc8M79w0QyM',
'Content-Type': 'application/json'
}
});
require 'net/http'
uri = URI('https://api.callbell.eu/v1/contacts')
req = Net::HTTP::Get.new(uri)
req.content_type = 'application/json'
req['Authorization'] = 'Bearer test_gshuPaZoeEG6ovbc8M79w0QyM'
req_options = {
use_ssl: uri.scheme == 'https'
}
res = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(req)
end
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "https://api.callbell.eu/v1/contacts", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer test_gshuPaZoeEG6ovbc8M79w0QyM")
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.callbell.eu/v1/contacts');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer test_gshuPaZoeEG6ovbc8M79w0QyM',
'Content-Type: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
import requests
headers = {
'Authorization': 'Bearer test_gshuPaZoeEG6ovbc8M79w0QyM',
'Content-Type': 'application/json',
}
response = requests.get('https://api.callbell.eu/v1/contacts', headers=headers)
using System.Net.Http;
using System.Net.Http.Headers;
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://api.callbell.eu/v1/contacts");
request.Headers.Add("Authorization", "Bearer test_gshuPaZoeEG6ovbc8M79w0QyM");
request.Content = new StringContent("");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
class Main {
public static void main(String[] args) throws IOException {
URL url = new URL("https://api.callbell.eu/v1/contacts");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
httpConn.setRequestMethod("GET");
httpConn.setRequestProperty("Authorization", "Bearer test_gshuPaZoeEG6ovbc8M79w0QyM");
httpConn.setRequestProperty("Content-Type", "application/json");
InputStream responseStream = httpConn.getResponseCode() / 100 == 2
? httpConn.getInputStream()
: httpConn.getErrorStream();
Scanner s = new Scanner(responseStream).useDelimiter("\\A");
String response = s.hasNext() ? s.next() : "";
System.out.println(response);
}
}
extern crate reqwest;
use reqwest::header;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut headers = header::HeaderMap::new();
headers.insert("Authorization", "Bearer test_gshuPaZoeEG6ovbc8M79w0QyM".parse().unwrap());
headers.insert("Content-Type", "application/json".parse().unwrap());
let client = reqwest::blocking::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.build()
.unwrap();
let res = client.get("https://api.callbell.eu/v1/contacts")
.headers(headers)
.send()?
.text()?;
println!("{}", res);
Ok(())
}
Respuesta
| Parámetro | Tipo | Descripción |
|---|---|---|
contacts | Contacto[] | Una lista de contactos. |
meta | object | Metadatos de paginación: page y pages para las solicitudes por páginas, más next, el cursor que apunta al siguiente lote (null en el último lote). |
Ejemplo de respuesta
response.json
{
"contacts": [
{
"uuid": "414a6d692bd645ed803f2e7ce360d4c8",
"name": "John Doe",
"phoneNumber": "+123 456 789",
"avatarUrl": null,
"createdAt": "2020-11-13T21:08:53Z",
"source": "whatsapp",
"href": "https://dash.callbell.eu/contacts/414a6d692bd645ed803f2e7ce360d4c8",
"conversationHref": "https://dash.callbell.eu/chat/f3670b13446b412796238b1cd78899f9",
"assignedUser": "john.doe@email.com",
"tags": [
"sales",
"lead"
],
"customFields":{
"Stripe link": "https://stripe.com/contacts/cus1234567",
"Billing Address": "3 Abbey Rd, London"
}
},
...
{
"uuid": "ff8bec9363bc4c29b8b044eabf2afebd",
"name": "Mario Rossi",
"phoneNumber": "+33 11 22 33 44",
"avatarUrl": null,
"createdAt": "2021-02-24T20:33:06Z",
"source": "whatsapp",
"href": "https://dash.callbell.eu/contacts/ff8bec9363bc4c29b8b044eabf2afebd",
"conversationHref": "https://dash.callbell.eu/chat/f3670b13446b412796238b1cd78899f9",
"assignedUser": null,
"tags": [
"sales",
"lead",
"hot"
],
"customFields":{
"Stripe link": "https://stripe.com/contacts/cus124124153"
}
}
],
"meta": {
"page": 1,
"pages": 42,
"next": "eyJ0cyI6MTc1NDM4NDQwMDAwMCwiaWQiOjEyMzQ1fQ"
}
}
Ejemplo de respuesta (con include_field_types=true)
response.json
{
"contacts": [
{
"uuid": "414a6d692bd645ed803f2e7ce360d4c8",
"name": "John Doe",
"customFields": {
"Address": "Oxford Street 123",
"Join Date": "2024-01-15",
"Preferences": "[\"Newsletter\", \"Promotions\"]"
},
"customFieldsMetadata": {
"Address": { "value": "Oxford Street 123", "type": "text" },
"Join Date": { "value": "2024-01-15", "type": "date" },
"Preferences": { "value": ["Newsletter", "Promotions"], "type": "checkbox", "options": ["Newsletter", "Promotions", "Updates"] }
}
}
]
}