SmartCQ
API REST

Endpoint Contatti

GET, POST, PATCH su /api/v1/contacts e /api/v1/contacts/:id con esempi cURL, Node.js e Python.

Endpoint per leggere e scrivere contatti del tenant.

GET /api/v1/contacts

Lista paginata con cursor-based pagination.

Scope richiesto: contacts:read

Query params

ParamTipoDefaultDescrizione
limitint50Numero di contatti per pagina (1–200)
cursorISO timestampRestituisce contatti più vecchi di created_at < cursor. Lascia vuoto per la prima pagina.
emailStatusenumactive | unsubscribed | bounced | complained | suppressed | pending_review
stageenumlead | prospect | customer | ex_customer
includeArchivedboolfalseSe true, include i contatti archiviati

Esempio cURL

curl -s -H "Authorization: Bearer $SMARTCQ_KEY" \
  "https://app.smartcq.it/api/v1/contacts?limit=20&emailStatus=active"

Risposta 200

{
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000001",
      "email": "mario.rossi@example.com",
      "firstName": "Mario",
      "lastName": "Rossi",
      "emailStatus": "active",
      "stage": "lead",
      "source": "manual",
      "consentType": "contract",
      "tags": ["cliente-storico", "milano"],
      "archivedAt": null,
      "acquiredAt": "2026-01-15T08:00:00.000Z",
      "createdAt": "2026-01-15T08:00:00.000Z",
      "updatedAt": "2026-01-15T08:00:00.000Z"
    }
  ],
  "next": "2026-01-15T08:00:00.000Z"
}

Per la pagina successiva, passa il valore di next come ?cursor=. Quando next è null, sei all'ultima pagina.

Esempio paginazione completa (Node.js)

async function fetchAllContacts() {
  const all: Contact[] = [];
  let cursor: string | null = null;
  do {
    const url = new URL("https://app.smartcq.it/api/v1/contacts");
    url.searchParams.set("limit", "200");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.SMARTCQ_KEY}` },
    });
    const j = await res.json();
    all.push(...j.data);
    cursor = j.next;
  } while (cursor);
  return all;
}

GET /api/v1/contacts/:id

Recupera un singolo contatto.

Scope richiesto: contacts:read

Esempio

curl -s -H "Authorization: Bearer $SMARTCQ_KEY" \
  "https://app.smartcq.it/api/v1/contacts/00000000-0000-0000-0000-000000000001"

Risposta

  • 200: oggetto Contact (stesso schema della lista)
  • 404: contatto non trovato o non appartenente al tenant della chiave (no leak cross-tenant)

POST /api/v1/contacts

Crea un nuovo contatto. Idempotente per email all'interno dello stesso tenant.

Scope richiesto: contacts:write

Body

{
  "email": "mario.rossi@example.com",
  "firstName": "Mario",
  "lastName": "Rossi",
  "consentType": "contract",
  "tags": ["cliente-storico", "milano"]
}
CampoTipoObbligatorioNote
emailstring (email)Validato lato server
firstNamestringno
lastNamestringno
consentTypestringnocontract, consent, ...
tagsstring[]noNomi dei tag (devono già esistere nel tenant)

Nota — I tag devono già esistere nel tenant. Se passi un nome inesistente, ricevi 400 unknown_tag. Crea i tag dalla UI prima.

Esempio cURL

curl -s -X POST \
  -H "Authorization: Bearer $SMARTCQ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"mario.rossi@example.com","firstName":"Mario"}' \
  "https://app.smartcq.it/api/v1/contacts"

Risposta

  • 201: oggetto Contact appena creato
  • 400: body malformato o tag inesistente
  • 409: email già presente nel tenant (con existing.id nel payload errore)
// 409
{
  "error": {
    "code": "conflict",
    "message": "Contatto già esistente con questa email",
    "existing": { "id": "00000000-0000-0000-0000-000000000001", "status": "active" }
  }
}

Esempio Python

import os
import requests

resp = requests.post(
    "https://app.smartcq.it/api/v1/contacts",
    headers={"Authorization": f"Bearer {os.environ['SMARTCQ_KEY']}"},
    json={
        "email": "mario.rossi@example.com",
        "firstName": "Mario",
        "consentType": "contract",
    },
)

if resp.status_code == 409:
    existing = resp.json()["error"]["existing"]
    print(f"Già esistente: {existing['id']}")
else:
    resp.raise_for_status()
    print(resp.json())

PATCH /api/v1/contacts/:id

Modifica un contatto esistente. Solo i campi presenti nel body sono aggiornati.

Scope richiesto: contacts:write

Body (tutti i campi opzionali)

{
  "firstName": "Mario",
  "lastName": "Rossi",
  "emailStatus": "unsubscribed",
  "stage": "prospect",
  "consentType": "contract"
}

Esempio cURL

curl -s -X PATCH \
  -H "Authorization: Bearer $SMARTCQ_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stage":"prospect"}' \
  "https://app.smartcq.it/api/v1/contacts/00000000-0000-0000-0000-000000000001"

Risposta

  • 200: oggetto Contact aggiornato
  • 400: body malformato (es. stage con valore sconosciuto)
  • 404: contatto non trovato o non del tenant

On this page