> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crmspark.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript — referência de recursos

> Métodos do cliente sparkcrm por recurso — entrypoints, chats, formulários, mensageria — com parâmetros, respostas e exemplos.

Esta página descreve a superfície atual do pacote [`sparkcrm`](https://www.npmjs.com/package/sparkcrm), alinhada ao [OpenAPI do gateway](https://gateway.crmspark.com.br/swagger-json). A árvore de chamadas segue o padrão `client.<recurso>.<método>()`.

Para autenticação, instalação e exemplos iniciais, veja [Começar com TypeScript](/sdks/typescript/introducao).

## Visão geral do cliente

```ts theme={null}
import SparkCRM from "sparkcrm";

const client = new SparkCRM({ apiKey: "sk_…" });

client.entrypoints   // canais (entrypoints)
client.chats         // upsert de conversas DM
client.forms         // formulários públicos
client.messaging     // mídia + chats
client.campaigns     // disparos em massa
client.messageTemplates // modelos de mensagem
// client.webhooks   → apenas tipos exportados (sem métodos HTTP)
```

***

## Entrypoints

Canais de entrada configurados na organização (WhatsApp Business, WhatsApp Lite, Instagram, Telegram).

### `client.entrypoints.list(params?)`

**HTTP:** `GET /v1/entrypoints`

| Parâmetro (`EntrypointListParams`) | Tipo                                                               | Descrição             |
| ---------------------------------- | ------------------------------------------------------------------ | --------------------- |
| `platform`                         | `"whatsapp"` \| `"whatsapp_lite"` \| `"instagram"` \| `"telegram"` | Filtra por plataforma |

**Retorno:** `EntrypointListResponse` com `entrypoints[]` (`id`, `name`, `platform`, `funnelStepId`, `displayName?`, `state?` em WhatsApp Lite).

```ts theme={null}
const all = await client.entrypoints.list();
const ig = await client.entrypoints.list({ platform: "instagram" });
```

### `client.entrypoints.retrieve(id)`

**HTTP:** `GET /v1/entrypoints/{id}`

**Retorno:** `EntrypointRetrieveResponse` com `entrypoint` discriminado por `platform` (campos extras como `isCoexistence` no WhatsApp Business, `state` no Lite).

```ts theme={null}
const { entrypoint } = await client.entrypoints.retrieve("ep_…");
```

***

## Chats

Conversas diretas (DM) no WhatsApp ou WhatsApp Lite. A plataforma é inferida pelo `entrypointId`. O telefone é normalizado para E.164.

Use o upsert individual quando precisar dos IDs na hora. Use o lote quando for importar muitos contatos e puder esperar o processamento em background (a resposta **não** inclui `chatId` / `leadId`).

### `client.chats.upsert(body)`

**HTTP:** `POST /v1/chats` → `201` (criado) ou `200` (já existia)

| Campo (`ChatUpsertParams`) | Obrigatório | Descrição                                                             |
| -------------------------- | ----------- | --------------------------------------------------------------------- |
| `entrypointId`             | sim         | Canal de origem (WhatsApp ou WhatsApp Lite)                           |
| `phone`                    | sim         | Telefone em formato livre; o Spark normaliza                          |
| `name`                     | não         | Nome exibido no chat; se o chat já existir, atualiza quando informado |
| `triggerAutomations`       | não         | Padrão `true`. Dispara automações ao criar um lead ou chat novo       |

**Retorno:** `ChatUpsertResponse` — `chatId` e `leadId`.

```ts theme={null}
const { chatId, leadId } = await client.chats.upsert({
  entrypointId: "wep_…",
  phone: "5511987654321",
  name: "Maria Silva",
});
```

### `client.chats.upsertBatch(body)`

**HTTP:** `POST /v1/chats/batch` → `202`

Enfileira até 500 conversas para o mesmo canal. O Spark processa cada item em background com a mesma regra do upsert individual (cria ou atualiza). Itens com telefone inválido ou limite de plano são ignorados no processamento, sem falhar o lote inteiro.

| Campo (`ChatUpsertBatchParams`) | Obrigatório | Descrição                              |
| ------------------------------- | ----------- | -------------------------------------- |
| `entrypointId`                  | sim         | Canal compartilhado por todos os itens |
| `triggerAutomations`            | não         | Padrão `true` para o lote              |
| `batch`                         | sim         | 1 a 500 itens com `phone` e `name?`    |

**Retorno:** `ChatUpsertBatchResponse` — `{ queued: number }`. Não há IDs de chat ou lead nesta resposta.

```ts theme={null}
const { queued } = await client.chats.upsertBatch({
  entrypointId: "wep_…",
  batch: [
    { phone: "5511987654321", name: "Maria Silva" },
    { phone: "5511912345678" },
  ],
});

console.log(`enfileirados: ${queued}`);
```

<Note>
  O lote é assíncrono. Para reagir a conversas novas, use o webhook [`chats.created`](/sdks/typescript/webhooks-e-tipos).
</Note>

***

## Forms (formulários)

Formulários de captação publicados com ID público de 16 caracteres. Conceito de produto: [Formulários de captação](/conceitos/formularios-de-captacao).

### `client.forms.retrieve(id)`

**HTTP:** `GET /v1/forms/{id}`

**Retorno:** `FormRetrieveResponse` — `form` com `name`, `description`, `flow` (nós e conexões do canvas) e `iframeEmbedAllowedOrigins`.

```ts theme={null}
const { form } = await client.forms.retrieve(publicFormId);
```

### `client.forms.retrieveEmbedFramePolicy(id)`

**HTTP:** `GET /v1/forms/{id}/embed-frame-policy`

**Retorno:** `FormRetrieveEmbedFramePolicyResponse` — lista de origens HTTPS permitidas para iframe (vazia = sem restrição por origem).

```ts theme={null}
const policy = await client.forms.retrieveEmbedFramePolicy(publicFormId);
```

### `client.forms.submitResponse(id, body)`

**HTTP:** `POST /v1/forms/{id}/submit` → `201`

| Campo (`FormSubmitResponseParams`) | Obrigatório | Descrição                                                             |
| ---------------------------------- | ----------- | --------------------------------------------------------------------- |
| `name`                             | sim         | Nome do lead                                                          |
| `phone`                            | sim         | Telefone (formato aceito pelo backend)                                |
| `answers`                          | não         | Respostas das perguntas (`questionKey` + `value` string ou string\[]) |

**Retorno:** `FormSubmitResponseResponse` — `submissionId` e `outcomes[]` com `platform`, `leadId`, `chatId` por destino WhatsApp.

```ts theme={null}
const result = await client.forms.submitResponse(publicFormId, {
  name: "João",
  phone: "5581987654321",
  answers: [{ questionKey: "porte", value: "pequena" }],
});
```

***

## Messaging

### `client.messaging.uploadMedia(body)`

**HTTP:** `POST /v1/messaging/media` (multipart)

| Campo   | Descrição                                                                         |
| ------- | --------------------------------------------------------------------------------- |
| `files` | Array de arquivos (`Uploadable`: `File`, `Blob`, buffer, stream conforme runtime) |

**Retorno:** `MessagingUploadMediaResponse` — array por arquivo: `{ success: true, id, name, url }` ou `{ success: false, name }`.

Use os `id` retornados em `sendMessage` (`mediaIds` ou `audioId`).

```ts theme={null}
const results = await client.messaging.uploadMedia({
  files: [file],
});
```

### `client.messaging.chats.listMessages(chatId, params?)`

**HTTP:** `GET /v1/messaging/chats/{chatId}`

| Parâmetro | Descrição                           |
| --------- | ----------------------------------- |
| `limit`   | Tamanho da página (1–50; padrão 20) |
| `cursor`  | Cursor para mensagens mais antigas  |

**Retorno:** `ChatListMessagesResponse` — `records[]` (mensagem completa com `text`, `type`, `status`, `media`, `sender`, etc.) e `nextCursor?`.

Mensagens vêm **mais recentes primeiro**.

```ts theme={null}
const page = await client.messaging.chats.listMessages(chatId, {
  limit: 30,
});

if (page.nextCursor) {
  const older = await client.messaging.chats.listMessages(chatId, {
    cursor: page.nextCursor,
  });
}
```

### `client.messaging.chats.sendMessage(chatId, body)`

**HTTP:** `POST /v1/messaging/chats/{chatId}` → `204`

| Campo (`ChatSendMessageParams`) | Descrição                                        |
| ------------------------------- | ------------------------------------------------ |
| `text`                          | Texto da mensagem                                |
| `mediaIds`                      | IDs de mídia do upload                           |
| `audioId`                       | Áudio único (sem `text` nem outras mídias)       |
| `replyToId`                     | Responder a uma mensagem                         |
| `delay`                         | Atraso em segundos antes do envio                |
| `instagramDelivery`             | `"dm"` \| `"comment_reply"` \| `"private_reply"` |
| `instagramSourceMessageId`      | ID da mensagem de origem no Instagram            |

```ts theme={null}
await client.messaging.chats.sendMessage(chatId, {
  text: "Confirmado para amanhã às 10h.",
  replyToId: messageId,
});
```

### Enviar modelo de mensagem (`templates`)

**HTTP:** `POST /v1/messaging/chats/{chatId}/templates` → `204`

Corpo (espelha `SendPublicTemplateBodyDto` na API):

| Campo             | Obrigatório | Descrição                            |
| ----------------- | ----------- | ------------------------------------ |
| `templateId`      | sim         | ID do modelo no Spark                |
| `commonVariables` | não         | Variáveis manuais: `var1`, `var2`, … |
| `replyToId`       | não         | Responder em thread                  |

Variáveis automáticas não vão no body — o Spark preenche com dados do chat. Veja [Modelos de mensagem](/conceitos/modelos-de-mensagem).

```ts theme={null}
await client.post(`/v1/messaging/chats/${chatId}/templates`, {
  body: {
    templateId: "tpl_…",
    commonVariables: {
      var1: "Black Friday",
      var2: "20OFF",
    },
  },
});
```

<Note title="Versões do pacote">
  Novas versões do `sparkcrm` podem expor `client.messaging.chats.sendTemplate(chatId, body)` com o mesmo contrato. Confira o [api.md](https://github.com/gepetojj/spark-typescript/blob/main/api.md) da versão instalada.
</Note>

***

## Campanhas (disparos em massa)

Criar, segmentar, iniciar e acompanhar campanhas de mensagem. Guia completo: [Disparos pela API](/api-reference/campaigns).

### `client.messageTemplates.list()`

**HTTP:** `GET /v1/message-templates`

**Retorno:** `MessageTemplateListResponse` com `templates[]` (`id`, `name`, `isOfficial`, `metaTemplateStatus`, …).

```ts theme={null}
const { templates } = await client.messageTemplates.list();
```

### `client.messageTemplates.retrieve(id)`

**HTTP:** `GET /v1/message-templates/{id}`

**Retorno:** detalhe do template com `items[]` (texto, mídia) e `commonVariables[]` (variáveis manuais exigidas no start).

```ts theme={null}
const template = await client.messageTemplates.retrieve("message_template_…");
console.log(template.commonVariables); // [{ key: "var1", label: "…", required: true }]
```

### `client.campaigns.getFilterSchema()`

**HTTP:** `GET /v1/campaigns/filters/schema`

**Retorno:** catálogo de campos, operadores e regras de combinação para montar filtros de público-alvo.

### `client.campaigns.previewAudience(body)`

**HTTP:** `POST /v1/campaigns/audience-preview`

**Body:** `{ filters?: CampaignFilter[] }`

**Retorno:** `{ estimatedCount: number }`

```ts theme={null}
const preview = await client.campaigns.previewAudience({
  filters: [
    {
      combinator: "and",
      statements: [
        { field: "chat.platform", operator: "equals", value: "whatsapp" },
      ],
    },
  ],
});
```

### `client.campaigns.create(body)`

**HTTP:** `POST /v1/campaigns`

**Body:** `name`, `platform`, `templateId`, `cadence`, `description?`, `filters?`

**Retorno:** `{ campaignId, status: "draft" }`

### `client.campaigns.start(id, body?)`

**HTTP:** `POST /v1/campaigns/{id}/start`

**Body:** `{ commonVariables?: Record<string, string> }` — variáveis manuais do template.

**Retorno:** `{ executionId, status: "processing" }`

### `client.campaigns.retrieve(id)` / `client.campaigns.list()`

**HTTP:** `GET /v1/campaigns/{id}` / `GET /v1/campaigns`

Detalhe com execuções ou lista resumida de campanhas.

### `client.campaigns.retrieveExecution(campaignId, executionId)`

**HTTP:** `GET /v1/campaigns/{id}/executions/{executionId}`

**Retorno:** `{ status, targetCount, sentCount, failedCount, progress }` — use para polling.

### `client.campaigns.cancel(id)`

**HTTP:** `POST /v1/campaigns/{id}/cancel`

Cancela execução em andamento. Sem body; resposta `204`.

***

## Tabela rápida de métodos

| Método SDK                       | Verbo / caminho                                   |
| -------------------------------- | ------------------------------------------------- |
| `entrypoints.list`               | `GET /v1/entrypoints`                             |
| `entrypoints.retrieve`           | `GET /v1/entrypoints/{id}`                        |
| `chats.upsert`                   | `POST /v1/chats`                                  |
| `chats.upsertBatch`              | `POST /v1/chats/batch`                            |
| `forms.retrieve`                 | `GET /v1/forms/{id}`                              |
| `forms.retrieveEmbedFramePolicy` | `GET /v1/forms/{id}/embed-frame-policy`           |
| `forms.submitResponse`           | `POST /v1/forms/{id}/submit`                      |
| `messaging.uploadMedia`          | `POST /v1/messaging/media`                        |
| `messaging.chats.listMessages`   | `GET /v1/messaging/chats/{chatId}`                |
| `messaging.chats.sendMessage`    | `POST /v1/messaging/chats/{chatId}`               |
| Envio de template                | `POST /v1/messaging/chats/{chatId}/templates`     |
| `messageTemplates.list`          | `GET /v1/message-templates`                       |
| `messageTemplates.retrieve`      | `GET /v1/message-templates/{id}`                  |
| `campaigns.getFilterSchema`      | `GET /v1/campaigns/filters/schema`                |
| `campaigns.previewAudience`      | `POST /v1/campaigns/audience-preview`             |
| `campaigns.create`               | `POST /v1/campaigns`                              |
| `campaigns.list`                 | `GET /v1/campaigns`                               |
| `campaigns.retrieve`             | `GET /v1/campaigns/{id}`                          |
| `campaigns.start`                | `POST /v1/campaigns/{id}/start`                   |
| `campaigns.retrieveExecution`    | `GET /v1/campaigns/{id}/executions/{executionId}` |
| `campaigns.cancel`               | `POST /v1/campaigns/{id}/cancel`                  |

***

## Requisições fora do catálogo tipado

O cliente expõe `get`, `post`, `put`, `patch`, `delete` com as mesmas opções de retry, timeout e cabeçalhos — útil para endpoints novos antes de uma release do SDK:

```ts theme={null}
await client.get("/v1/entrypoints", { query: { platform: "telegram" } });
```

Parâmetros não documentados podem ser enviados com `// @ts-expect-error` ou via `query` / `body` / `headers` explícitos, conforme a [documentação avançada](/sdks/typescript/configuracao-avancada).

## Tipos principais exportados

Importe de `sparkcrm` ou use o namespace `SparkCRM`:

| Área        | Tipos úteis                                                                                                                                     |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Entrypoints | `EntrypointListResponse`, `EntrypointRetrieveResponse`, `EntrypointListParams`                                                                  |
| Chats       | `ChatUpsertParams`, `ChatUpsertResponse`, `ChatUpsertBatchParams`, `ChatUpsertBatchResponse`                                                    |
| Forms       | `FormRetrieveResponse`, `FormSubmitResponseParams`, `FormSubmitResponseResponse`                                                                |
| Messaging   | `ChatListMessagesResponse`, `ChatSendMessageParams`, `MessagingUploadMediaParams`, `MessagingUploadMediaResponse`                               |
| Campanhas   | `CampaignCreateParams`, `CampaignCreateResponse`, `CampaignStartParams`, `CampaignExecutionRetrieveResponse`, `MessageTemplateRetrieveResponse` |
| Webhooks    | `SparkWebhookBody`, `MessagesReceivedWebhook`, `MessagesSentWebhook`, `ChatsCreatedWebhook`                                                     |
| Erros       | `APIError`, `RateLimitError`, `AuthenticationError`, …                                                                                          |

Lista completa no repositório: [api.md](https://github.com/gepetojj/spark-typescript/blob/main/api.md).
